split internal/external logic during confirmation

onReadyToConfirmListener now only contains external logic
conversion of ParamValues to Arguments is moved outside

Bug: 280692953
Test: covered by existing tests
Change-Id: I563d59866c6530fb87274b8dae03aa8658e7e32f
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
index d50a676..a720034 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
@@ -93,7 +93,11 @@
          * @suppress
          */
         @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-        protected open val sessionBridge: SessionBridge<ExecutionSessionT, ConfirmationT>? = null
+        protected open val sessionBridge: SessionBridge<
+            ExecutionSessionT,
+            ArgumentsT,
+            ConfirmationT
+        >? = null
 
         @Suppress("UNCHECKED_CAST")
         private fun asBuilder(): BuilderT {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListener.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListener.kt
new file mode 100644
index 0000000..ed30805
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListener.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.appactions.interaction.capabilities.core.impl.task
+
+import androidx.annotation.RestrictTo
+import androidx.appactions.interaction.capabilities.core.ConfirmationOutput
+
+/**
+ * Generic onReadyToConfirm listener for a task capability.
+ * This should wrap only the external Session#onReadyToConfirm and nothing else.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+interface OnReadyToConfirmListener<ArgumentsT, ConfirmationT> {
+    /** onReadyToConfirm callback for a task session. */
+    suspend fun onReadyToConfirm(arguments: ArgumentsT): ConfirmationOutput<ConfirmationT>
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListenerInternal.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListenerInternal.kt
deleted file mode 100644
index ffbfb24..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListenerInternal.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package androidx.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.ConfirmationOutput
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.proto.ParamValue
-
-/**
- * Generic onReadyToConfirm listener for a task capability. This is the entry point to specific
- * onReadyToConfirm listeners. For example, Search/Update sub-BIIs factories may invoke specific
- * onReadyToConfirm listeners for that BII.
- */
-interface OnReadyToConfirmListenerInternal<ConfirmationT> {
-    /** onReadyToConfirm callback for a task capability. */
-    @Throws(StructConversionException::class)
-    suspend fun onReadyToConfirm(
-        args: Map<String, List<ParamValue>>
-    ): ConfirmationOutput<ConfirmationT>
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt
index 6242b6f8..a31759c 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt
@@ -26,7 +26,10 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 fun interface SessionBridge<
     ExecutionSessionT,
+    ArgumentsT,
     ConfirmationT
 > {
-    fun createTaskHandler(externalSession: ExecutionSessionT): TaskHandler<ConfirmationT>
+    fun createTaskHandler(
+        externalSession: ExecutionSessionT
+    ): TaskHandler<ArgumentsT, ConfirmationT>
 }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt
index fc9eeaf..4dee5fa 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt
@@ -46,7 +46,7 @@
     private val actionSpec: ActionSpec<ArgumentsT, OutputT>,
     private val property: Map<String, Property<*>>,
     private val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSessionT?,
-    private val sessionBridge: SessionBridge<ExecutionSessionT, ConfirmationT>,
+    private val sessionBridge: SessionBridge<ExecutionSessionT, ArgumentsT, ConfirmationT>,
     private val sessionUpdaterSupplier: Supplier<SessionUpdaterT>
 ) : Capability(id) {
 
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt
index 1f577f5..6ef8d2b 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt
@@ -41,7 +41,7 @@
     override val sessionId: String,
     actionSpec: ActionSpec<ArgumentsT, OutputT>,
     appAction: AppAction,
-    taskHandler: TaskHandler<ConfirmationT>,
+    taskHandler: TaskHandler<ArgumentsT, ConfirmationT>,
     externalSession: BaseExecutionSession<ArgumentsT, OutputT>,
     private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
 ) : CapabilitySession, TaskUpdateHandler {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
index 790a750..9601c24 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
@@ -29,24 +29,24 @@
 
 /** Container of multi-turn Task related function references. */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-data class TaskHandler<ConfirmationT>
+data class TaskHandler<ArgumentsT, ConfirmationT>
 internal constructor(
     internal val taskParamMap: Map<String, TaskParamBinding<*>>,
     internal val confirmationDataBindings: Map<String, (ConfirmationT) -> List<ParamValue>>,
-    internal val onReadyToConfirmListener: OnReadyToConfirmListenerInternal<ConfirmationT>?,
+    internal val onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>?,
 ) {
-    class Builder<ConfirmationT>() {
+    class Builder<ArgumentsT, ConfirmationT>() {
         private val mutableTaskParamMap = mutableMapOf<String, TaskParamBinding<*>>()
         private val confirmationDataBindings =
             mutableMapOf<String, (ConfirmationT) -> List<ParamValue>>()
-        private var onReadyToConfirmListener: OnReadyToConfirmListenerInternal<ConfirmationT>? =
+        private var onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>? =
             null
 
         fun <ValueTypeT> registerInventoryTaskParam(
             paramName: String,
             listener: InventoryListener<ValueTypeT>,
             converter: ParamValueConverter<ValueTypeT>,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             mutableTaskParamMap[paramName] =
                 TaskParamBinding(
                     paramName,
@@ -62,7 +62,7 @@
             paramName: String,
             listener: InventoryListListener<ValueTypeT>,
             converter: ParamValueConverter<ValueTypeT>,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             mutableTaskParamMap[paramName] =
                 TaskParamBinding(
                     paramName,
@@ -80,7 +80,7 @@
             converter: ParamValueConverter<ValueTypeT>,
             entityConverter: EntityConverter<ValueTypeT>,
             searchActionConverter: SearchActionConverter<ValueTypeT>,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             mutableTaskParamMap[paramName] =
                 TaskParamBinding(
                     paramName,
@@ -98,7 +98,7 @@
             converter: ParamValueConverter<ValueTypeT>,
             entityConverter: EntityConverter<ValueTypeT>,
             searchActionConverter: SearchActionConverter<ValueTypeT>,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             mutableTaskParamMap[paramName] =
                 TaskParamBinding(
                     paramName,
@@ -114,7 +114,7 @@
             paramName: String,
             listener: ValueListener<ValueTypeT>,
             converter: ParamValueConverter<ValueTypeT>,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             mutableTaskParamMap[paramName] =
                 TaskParamBinding(
                     paramName,
@@ -130,7 +130,7 @@
             paramName: String,
             listener: ValueListener<List<ValueTypeT>>,
             converter: ParamValueConverter<ValueTypeT>,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             mutableTaskParamMap[paramName] =
                 TaskParamBinding(
                     paramName,
@@ -154,26 +154,25 @@
             paramName: String,
             confirmationGetter: (ConfirmationT) -> T?,
             converter: (T) -> ParamValue,
-        ): Builder<ConfirmationT> = apply {
+        ) = apply {
             confirmationDataBindings[paramName] = { output: ConfirmationT ->
                 listOfNotNull(confirmationGetter(output)).map(converter)
             }
         }
 
-        /** Sets the onReadyToConfirmListener for this capability. */
-        fun setOnReadyToConfirmListenerInternal(
-            onReadyToConfirmListener: OnReadyToConfirmListenerInternal<ConfirmationT>,
-        ): Builder<ConfirmationT> = apply {
+        /** Sets the onReadyToConfirmListener for this session. */
+        fun setOnReadyToConfirmListener(
+            onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>,
+        ) = apply {
             this.onReadyToConfirmListener = onReadyToConfirmListener
         }
 
-        fun build(): TaskHandler<ConfirmationT> {
-            return TaskHandler(
-                mutableTaskParamMap.toMap(),
-                confirmationDataBindings,
-                onReadyToConfirmListener,
-            )
-        }
+        fun build() = TaskHandler(
+            mutableTaskParamMap.toMap(),
+            confirmationDataBindings,
+            onReadyToConfirmListener,
+        )
+
         companion object {
             val GROUND_IF_NO_IDENTIFIER = { paramValue: ParamValue -> !paramValue.hasIdentifier() }
             val GROUND_NEVER = { _: ParamValue -> false }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt
index f39671e..3b4ca84 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt
@@ -60,7 +60,7 @@
     private val sessionId: String,
     private val actionSpec: ActionSpec<ArgumentsT, OutputT>,
     private val appAction: AppActionsContext.AppAction,
-    private val taskHandler: TaskHandler<ConfirmationT>,
+    private val taskHandler: TaskHandler<ArgumentsT, ConfirmationT>,
     private val externalSession: BaseExecutionSession<ArgumentsT, OutputT>,
     private val scope: CoroutineScope,
 ) {
@@ -450,9 +450,12 @@
     private suspend fun getFulfillmentResponseForConfirmation(
         finalArguments: Map<String, List<ParamValue>>,
     ): FulfillmentResponse {
+        val arguments = actionSpec.buildArguments(finalArguments)
+        requireNotNull(taskHandler.onReadyToConfirmListener) {
+            "caller must ensure TaskHandler.onReadyToConfirmListener is not null"
+        }
         val result = invokeExternalSuspendBlock("onReadyToConfirm") {
-            // TODO(b/280692953) split onReadyToConfirmListener to external & internal blocks
-            taskHandler.onReadyToConfirmListener!!.onReadyToConfirm(finalArguments)
+            taskHandler.onReadyToConfirmListener.onReadyToConfirm(arguments)
         }
         val fulfillmentResponse = FulfillmentResponse.newBuilder()
         convertToConfirmationOutput(result)?.let { fulfillmentResponse.confirmationData = it }
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImplTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImplTest.kt
index fc5728d..241d5f3 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImplTest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImplTest.kt
@@ -92,7 +92,7 @@
                         Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
                 }
             },
-            sessionBridge = { TaskHandler.Builder<Confirmation>().build() },
+            sessionBridge = { TaskHandler.Builder<Arguments, Confirmation>().build() },
             sessionUpdaterSupplier = ::EmptyTaskUpdater
         )
     private val hostProperties: HostProperties =
@@ -138,7 +138,7 @@
                         Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
                 }
             },
-            sessionBridge = { TaskHandler.Builder<Confirmation>().build() },
+            sessionBridge = { TaskHandler.Builder<Arguments, Confirmation>().build() },
             sessionUpdaterSupplier = ::EmptyTaskUpdater
         )
         mutableEntityList.add(StringValue.of("entity1"))
@@ -185,7 +185,7 @@
             createCapability(
                 SINGLE_REQUIRED_FIELD_PROPERTY,
                 { externalSession },
-                { TaskHandler.Builder<Confirmation>().build() },
+                { TaskHandler.Builder<Arguments, Confirmation>().build() },
                 ::EmptyTaskUpdater
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
@@ -212,7 +212,9 @@
                             )
                     }
                 },
-                sessionBridge = SessionBridge { TaskHandler.Builder<Confirmation>().build() },
+                sessionBridge = SessionBridge {
+                    TaskHandler.Builder<Arguments, Confirmation>().build()
+                },
                 sessionUpdaterSupplier = ::EmptyTaskUpdater
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
@@ -289,7 +291,9 @@
         val capability: Capability = createCapability(
             SINGLE_REQUIRED_FIELD_PROPERTY,
             sessionFactory = { _ -> externalSession },
-            sessionBridge = SessionBridge { TaskHandler.Builder<Confirmation>().build() },
+            sessionBridge = SessionBridge {
+                TaskHandler.Builder<Arguments, Confirmation>().build()
+            },
             sessionUpdaterSupplier = ::RequiredTaskUpdater
         )
         val session = capability.createSession("mySessionId", hostProperties)
@@ -327,7 +331,9 @@
                             )
                     }
                 },
-                sessionBridge = SessionBridge { TaskHandler.Builder<Confirmation>().build() },
+                sessionBridge = SessionBridge {
+                    TaskHandler.Builder<Arguments, Confirmation>().build()
+                },
                 sessionUpdaterSupplier = ::RequiredTaskUpdater
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
@@ -376,8 +382,12 @@
         val sessionBridge =
             SessionBridge<
                 CapabilityTwoStrings.ExecutionSession,
+                CapabilityTwoStrings.Arguments,
                 CapabilityTwoStrings.Confirmation> {
-                TaskHandler.Builder<CapabilityTwoStrings.Confirmation>()
+                TaskHandler.Builder<
+                    CapabilityTwoStrings.Arguments,
+                    CapabilityTwoStrings.Confirmation
+                >()
                     .registerValueTaskParam(
                         "stringSlotA",
                         AUTO_ACCEPT_STRING_VALUE,
@@ -467,8 +477,12 @@
         val sessionBridge =
             SessionBridge<
                 CapabilityTwoStrings.ExecutionSession,
+                CapabilityTwoStrings.Arguments,
                 CapabilityTwoStrings.Confirmation> {
-                TaskHandler.Builder<CapabilityTwoStrings.Confirmation>()
+                TaskHandler.Builder<
+                    CapabilityTwoStrings.Arguments,
+                    CapabilityTwoStrings.Confirmation
+                >()
                     .registerValueTaskParam(
                         "stringSlotA",
                         AUTO_ACCEPT_STRING_VALUE,
@@ -543,7 +557,9 @@
             createCapability(
                 property,
                 sessionFactory = { _ -> ExecutionSession.DEFAULT },
-                sessionBridge = SessionBridge { TaskHandler.Builder<Confirmation>().build() },
+                sessionBridge = SessionBridge {
+                    TaskHandler.Builder<Arguments, Confirmation>().build()
+                },
                 sessionUpdaterSupplier = ::EmptyTaskUpdater
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
@@ -621,8 +637,8 @@
                     }
                 },
                 sessionBridge =
-                SessionBridge<ExecutionSession, Confirmation> { session ->
-                    val builder = TaskHandler.Builder<Confirmation>()
+                SessionBridge<ExecutionSession, Arguments, Confirmation> { session ->
+                    val builder = TaskHandler.Builder<Arguments, Confirmation>()
                     session.requiredStringListener?.let {
                             listener: AppEntityListener<String> ->
                         builder.registerAppEntityTaskParam(
@@ -777,8 +793,12 @@
         val sessionBridge =
             SessionBridge<
                 CapabilityStructFill.ExecutionSession,
+                CapabilityStructFill.Arguments,
                 CapabilityStructFill.Confirmation> { session ->
-                TaskHandler.Builder<CapabilityStructFill.Confirmation>()
+                TaskHandler.Builder<
+                    CapabilityStructFill.Arguments,
+                    CapabilityStructFill.Confirmation
+                >()
                     .registerAppEntityTaskParam(
                         "listItem",
                         session.listItemListener,
@@ -983,7 +1003,9 @@
             createCapability(
                 property,
                 sessionFactory = sessionFactory,
-                sessionBridge = SessionBridge { TaskHandler.Builder<Confirmation>().build() },
+                sessionBridge = SessionBridge {
+                    TaskHandler.Builder<Arguments, Confirmation>().build()
+                },
                 sessionUpdaterSupplier = ::EmptyTaskUpdater
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
@@ -1024,8 +1046,8 @@
                 }
             }
         var onReadyToConfirm =
-            object : OnReadyToConfirmListenerInternal<Confirmation> {
-                override suspend fun onReadyToConfirm(args: Map<String, List<ParamValue>>):
+            object : OnReadyToConfirmListener<Arguments, Confirmation> {
+                override suspend fun onReadyToConfirm(arguments: Arguments):
                     ConfirmationOutput<Confirmation> {
                     return ConfirmationOutput.Builder<Confirmation>()
                         .setConfirmation(
@@ -1043,8 +1065,8 @@
                 property,
                 sessionFactory = sessionFactory,
                 sessionBridge = SessionBridge {
-                    TaskHandler.Builder<Confirmation>()
-                        .setOnReadyToConfirmListenerInternal(onReadyToConfirm)
+                    TaskHandler.Builder<Arguments, Confirmation>()
+                        .setOnReadyToConfirmListener(onReadyToConfirm)
                         .build()
                 },
                 sessionUpdaterSupplier = ::EmptyTaskUpdater
@@ -1092,7 +1114,9 @@
             createCapability(
                 property,
                 sessionFactory = sessionFactory,
-                sessionBridge = SessionBridge { TaskHandler.Builder<Confirmation>().build() },
+                sessionBridge = SessionBridge {
+                    TaskHandler.Builder<Arguments, Confirmation>().build()
+                },
                 sessionUpdaterSupplier = ::EmptyTaskUpdater
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
@@ -1235,9 +1259,13 @@
             setProperty(SINGLE_REQUIRED_FIELD_PROPERTY)
         }
 
-        override val sessionBridge: SessionBridge<ExecutionSession, Confirmation> = SessionBridge {
+        override val sessionBridge: SessionBridge<
+            ExecutionSession,
+            Arguments,
+            Confirmation
+        > = SessionBridge {
                 session ->
-            val builder = TaskHandler.Builder<Confirmation>()
+            val builder = TaskHandler.Builder<Arguments, Confirmation>()
             session.requiredStringListener?.let {
                     listener: AppEntityListener<String> ->
                 builder.registerAppEntityTaskParam(
@@ -1386,7 +1414,7 @@
         private fun <SessionUpdaterT : AbstractTaskUpdater> createCapability(
             property: Map<String, Property<*>>,
             sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession,
-            sessionBridge: SessionBridge<ExecutionSession, Confirmation>,
+            sessionBridge: SessionBridge<ExecutionSession, Arguments, Confirmation>,
             sessionUpdaterSupplier: Supplier<SessionUpdaterT>
         ): TaskCapabilityImpl<
             Arguments,
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt
index 17ee321..6ffb63a 100644
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt
+++ b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt
@@ -57,7 +57,11 @@
             >(ACTION_SPEC) {
         private var properties = mutableMapOf<String, Property<*>>()
 
-        override val sessionBridge: SessionBridge<ExecutionSession, Confirmation> = SESSION_BRIDGE
+        override val sessionBridge: SessionBridge<
+            ExecutionSession,
+            Arguments,
+            Confirmation
+        > = SESSION_BRIDGE
 
         override fun setExecutionSessionFactory(
             sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession
@@ -238,9 +242,9 @@
                 )
                 .build()
 
-        private val SESSION_BRIDGE = SessionBridge<ExecutionSession, Confirmation> {
+        private val SESSION_BRIDGE = SessionBridge<ExecutionSession, Arguments, Confirmation> {
                 session ->
-            val taskHandlerBuilder = TaskHandler.Builder<Confirmation>()
+            val taskHandlerBuilder = TaskHandler.Builder<Arguments, Confirmation>()
             session.nameListener?.let {
                 taskHandlerBuilder.registerValueTaskParam(
                     "timer.name",
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt
index 8678ac3..1105d83 100644
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt
+++ b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt
@@ -62,9 +62,9 @@
         Confirmation,
         ExecutionSession,
         >(ACTION_SPEC) {
-        override val sessionBridge = SessionBridge<ExecutionSession, Confirmation> {
+        override val sessionBridge = SessionBridge<ExecutionSession, Arguments, Confirmation> {
                 session ->
-            val builder = TaskHandler.Builder<Confirmation>()
+            val builder = TaskHandler.Builder<Arguments, Confirmation>()
             session.fieldOneListener?.let {
                 builder.registerValueTaskParam(
                     "fieldOne",