Merge changes Id3ac1704,I8355d9cd,I50037e80 into androidx-main

* changes:
  Remove MotionLayoutState Api
  Expand on MotionLayot Composables documentation
  Fix MotionLayout Composables parameters
diff --git a/OWNERS b/OWNERS
index 13e8cd6..e6c536a 100644
--- a/OWNERS
+++ b/OWNERS
@@ -26,6 +26,7 @@
 per-file *settings.gradle = set noparent
 per-file *settings.gradle = [email protected], [email protected]
 per-file *libraryversions.toml = [email protected]
+per-file *libraryversions.toml = [email protected], [email protected], [email protected]
 
 # Copybara can self-approve CLs within synced docs.
 per-file docs/** = [email protected]
\ No newline at end of file
diff --git a/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt b/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt
index 1174984..c5a9c26528 100644
--- a/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt
+++ b/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt
@@ -17,10 +17,8 @@
 package androidx.activity.compose.samples
 
 import androidx.activity.compose.BackHandler
-import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
 import androidx.annotation.Sampled
-import androidx.compose.material.Button
-import androidx.compose.material.Text
+import androidx.compose.material.TextField
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -30,12 +28,14 @@
 @Sampled
 @Composable
 fun BackHandler() {
-    var backPressedCount by remember { mutableStateOf(0) }
-    BackHandler { backPressedCount++ }
+    var text by remember { mutableStateOf("") }
 
-    val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher
+    TextField(
+        value = text,
+        onValueChange = { text = it }
+    )
 
-    Button(onClick = { dispatcher.onBackPressed() }) {
-        Text("Press Back count $backPressedCount")
+    BackHandler(text.isNotEmpty()) {
+        // handle back event
     }
 }
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 021c371..5362c618 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
@@ -77,7 +77,7 @@
     ) {
         private var id: String? = null
         private var property: PropertyT? = null
-        private var capabilityExecutor: CapabilityExecutor<ArgumentsT, OutputT>? = null
+        private var executionCallback: ExecutionCallback<ArgumentsT, OutputT>? = null
         private var sessionFactory: ExecutionSessionFactory<ExecutionSessionT>? = null
 
         /**
@@ -111,39 +111,40 @@
         }
 
         /**
-         * Sets the CapabilityExecutor for this capability.
+         * Sets the ExecutionCallback for this capability.
          *
-         * setExecutionSessionFactory and setExecutor are mutually exclusive, so calling one will
-         * nullify the other.
+         * [setExecutionSessionFactory] and [setExecutionCallback] are mutually exclusive, so
+         * calling one will nullify the other.
          *
-         * This method accepts a coroutine-based CapabilityExecutor instance. There is also an overload
-         * which accepts the CapabilityExecutorAsync instead.
+         * This method accepts a coroutine-based ExecutionCallback instance. There is also an
+         * overload which accepts the ExecutionCallbackAsync instead.
          */
-        fun setExecutor(capabilityExecutor: CapabilityExecutor<ArgumentsT, OutputT>) =
+        fun setExecutionCallback(executionCallback: ExecutionCallback<ArgumentsT, OutputT>) =
             asBuilder().apply {
-                this.capabilityExecutor = capabilityExecutor
+                this.executionCallback = executionCallback
             }
 
         /**
-         * Sets the CapabilityExecutorAsync for this capability.
+         * Sets the ExecutionCallbackAsync for this capability.
          *
-         * setExecutionSessionFactory and setExecutor are mutually exclusive, so calling one will
-         * nullify the other.
+         * setExecutionSessionFactory and setExecutionCallback are mutually exclusive, so calling
+         * one will nullify the other.
          *
-         * This method accepts the CapabilityExecutorAsync interface which returns a ListenableFuture.
+         * This method accepts the ExecutionCallbackAsync interface which returns a
+         * []ListenableFuture].
          */
-        fun setExecutor(
-            capabilityExecutorAsync: CapabilityExecutorAsync<ArgumentsT, OutputT>
+        fun setExecutionCallback(
+            executionCallbackAsync: ExecutionCallbackAsync<ArgumentsT, OutputT>
         ) = asBuilder().apply {
-            this.capabilityExecutor = capabilityExecutorAsync.toCapabilityExecutor()
+            this.executionCallback = executionCallbackAsync.toExecutionCallback()
         }
 
         /**
          * Sets the SessionBuilder instance which is used to create Session instaces for this
          * capability.
          *
-         * [setExecutionSessionFactory] and [setExecutor] are mutually exclusive, so calling one
-         * will nullify the other.
+         * [setExecutionSessionFactory] and [setExecutionCallback] are mutually exclusive, so
+         * calling one will nullify the other.
          */
         protected open fun setExecutionSessionFactory(
             sessionFactory: ExecutionSessionFactory<ExecutionSessionT>
@@ -155,16 +156,17 @@
         open fun build(): Capability {
             val checkedId = requireNotNull(id) { "setId must be called before build" }
             val checkedProperty = requireNotNull(property) { "property must not be null." }
-            if (capabilityExecutor != null) {
+            if (executionCallback != null) {
                 return SingleTurnCapabilityImpl(
                     checkedId,
                     actionSpec,
                     checkedProperty,
-                    capabilityExecutor!!
+                    executionCallback!!
                 )
             } else {
                 val checkedSessionFactory = requireNotNull(sessionFactory) {
-                    "either setExecutor or setExecutionSessionFactory must be called before build"
+                    "either setExecutionCallback or setExecutionSessionFactory" +
+                        " must be called before build"
                 }
                 return TaskCapabilityImpl(
                     checkedId,
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityExecutor.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallback.kt
similarity index 76%
rename from appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityExecutor.kt
rename to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallback.kt
index 01e9aae..87ff079 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityExecutor.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallback.kt
@@ -23,9 +23,9 @@
  * An interface of executing the action.
  *
  * Actions are executed asynchronously using Kotlin coroutines.
- * For a Future-based solution, see CapabilityExecutorAsync.
+ * For a Future-based solution, see ExecutionCallbackAsync.
  */
-fun interface CapabilityExecutor<ArgumentsT, OutputT> {
+fun interface ExecutionCallback<ArgumentsT, OutputT> {
     @get:RestrictTo(RestrictTo.Scope.LIBRARY)
     val uiHandle: Any
         get() = this
@@ -40,9 +40,9 @@
 }
 
 internal fun <ArgumentsT, OutputT>
-    CapabilityExecutorAsync<ArgumentsT, OutputT>.toCapabilityExecutor():
-    CapabilityExecutor<ArgumentsT, OutputT> = object : CapabilityExecutor<ArgumentsT, OutputT> {
-    override val uiHandle = this@toCapabilityExecutor
+    ExecutionCallbackAsync<ArgumentsT, OutputT>.toExecutionCallback():
+    ExecutionCallback<ArgumentsT, OutputT> = object : ExecutionCallback<ArgumentsT, OutputT> {
+    override val uiHandle = this@toExecutionCallback
     override suspend fun onExecute(arguments: ArgumentsT): ExecutionResult<OutputT> =
-        [email protected](arguments).await()
+        [email protected](arguments).await()
 }
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityExecutorAsync.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallbackAsync.kt
similarity index 94%
rename from appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityExecutorAsync.kt
rename to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallbackAsync.kt
index 73d04fd..239f6a4 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityExecutorAsync.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallbackAsync.kt
@@ -19,7 +19,7 @@
 import com.google.common.util.concurrent.ListenableFuture
 
 /** An ListenableFuture-based interface of executing an action. */
-fun interface CapabilityExecutorAsync<ArgumentsT, OutputT> {
+fun interface ExecutionCallbackAsync<ArgumentsT, OutputT> {
     /**
      * Calls to execute the action.
      *
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt
index 632ce37..e2ced1d 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt
@@ -62,7 +62,7 @@
 
     /**
      * The developer-provided external object (either a BaseExecutionSession instance or an
-     * CapabilityExecutor instance).
+     * ExecutionCallback instance).
      */
     val uiHandle: Any
 }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
index 4ff60e0..050d370 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
@@ -17,7 +17,7 @@
 package androidx.appactions.interaction.capabilities.core.impl
 
 import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutor
+import androidx.appactions.interaction.capabilities.core.ExecutionCallback
 import androidx.appactions.interaction.capabilities.core.Capability
 import androidx.appactions.interaction.capabilities.core.HostProperties
 import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
@@ -35,11 +35,11 @@
     id: String,
     val actionSpec: ActionSpec<PropertyT, ArgumentsT, OutputT>,
     val property: PropertyT,
-    val capabilityExecutor: CapabilityExecutor<ArgumentsT, OutputT>,
+    val executionCallback: ExecutionCallback<ArgumentsT, OutputT>,
 ) : Capability(id) {
     private val mutex = Mutex()
 
-    override val appAction: AppAction =
+    override val appAction: AppAction get() =
         actionSpec.convertPropertyToProto(property).toBuilder()
             .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
             .setIdentifier(id)
@@ -52,7 +52,7 @@
         return SingleTurnCapabilitySession(
             sessionId,
             actionSpec,
-            capabilityExecutor,
+            executionCallback,
             mutex,
         )
     }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
index 0bb184a..015147a 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
@@ -17,7 +17,7 @@
 package androidx.appactions.interaction.capabilities.core.impl
 
 import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutor
+import androidx.appactions.interaction.capabilities.core.ExecutionCallback
 import androidx.appactions.interaction.capabilities.core.ExecutionResult
 import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
 import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
@@ -42,7 +42,7 @@
     >(
     override val sessionId: String,
     private val actionSpec: ActionSpec<*, ArgumentsT, OutputT>,
-    private val capabilityExecutor: CapabilityExecutor<ArgumentsT, OutputT>,
+    private val executionCallback: ExecutionCallback<ArgumentsT, OutputT>,
     private val mutex: Mutex,
     private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
 ) : CapabilitySession {
@@ -51,7 +51,7 @@
     override val state: AppDialogState? = null
     override val isActive: Boolean get() = isActiveAtomic.get()
 
-    override val uiHandle: Any = capabilityExecutor.uiHandle
+    override val uiHandle: Any = executionCallback.uiHandle
 
     override fun destroy() {}
 
@@ -75,7 +75,7 @@
             try {
                 mutex.lock(owner = this@SingleTurnCapabilitySession)
                 UiHandleRegistry.registerUiHandle(uiHandle, sessionId)
-                val output = capabilityExecutor.onExecute(arguments)
+                val output = executionCallback.onExecute(arguments)
                 callback.onSuccess(convertToFulfillmentResponse(output))
             } catch (t: Throwable) {
                 callback.onError(ErrorStatusInternal.CANCELLED)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
index 34f1ddc..075d36f3 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
@@ -42,6 +42,7 @@
 import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.Optional;
 
@@ -213,8 +214,9 @@
                 @NonNull
                 @Override
                 public ParamValue toParamValue(LocalDate value) {
-                    // TODO(b/275456249): Implement backwards conversion.
-                    return ParamValue.getDefaultInstance();
+                    return ParamValue.newBuilder()
+                            .setStringValue(value.format(DateTimeFormatter.ISO_LOCAL_DATE))
+                            .build();
                 }
 
                 @Override
@@ -237,8 +239,9 @@
                 @NonNull
                 @Override
                 public ParamValue toParamValue(LocalTime value) {
-                    // TODO(b/275456249)): Implement backwards conversion.
-                    return ParamValue.getDefaultInstance();
+                    return ParamValue.newBuilder()
+                            .setStringValue(value.format(DateTimeFormatter.ISO_LOCAL_TIME))
+                            .build();
                 }
 
                 @Override
@@ -261,8 +264,7 @@
                 @NonNull
                 @Override
                 public ParamValue toParamValue(ZoneId value) {
-                    // TODO(b/275456249)): Implement backwards conversion.
-                    return ParamValue.getDefaultInstance();
+                    return ParamValue.newBuilder().setStringValue(value.getId()).build();
                 }
 
                 @Override
@@ -285,8 +287,9 @@
                 @NonNull
                 @Override
                 public ParamValue toParamValue(ZonedDateTime value) {
-                    // TODO(b/275456249)): Implement backwards conversion.
-                    return ParamValue.getDefaultInstance();
+                    return ParamValue.newBuilder()
+                            .setStringValue(value.format(DateTimeFormatter.ISO_ZONED_DATE_TIME))
+                            .build();
                 }
 
                 @Override
@@ -310,8 +313,7 @@
                 @NonNull
                 @Override
                 public ParamValue toParamValue(Duration value) {
-                    // TODO(b/275456249)): Implement backwards conversion.
-                    return ParamValue.getDefaultInstance();
+                    return ParamValue.newBuilder().setStringValue(value.toString()).build();
                 }
 
                 @Override
@@ -337,8 +339,9 @@
                 @NonNull
                 @Override
                 public ParamValue toParamValue(Call.CanonicalValue.CallFormat value) {
-                    // TODO(b/275456249)): Implement backwards conversion.
-                    return ParamValue.getDefaultInstance();
+                    return ParamValue.newBuilder()
+                        .setStringValue(value.getTextValue())
+                        .build();
                 }
 
                 @Override
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 fade42a..3c51e47 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
@@ -51,7 +51,7 @@
     private val sessionUpdaterSupplier: Supplier<SessionUpdaterT>
 ) : Capability(id) {
 
-    override val appAction: AppAction =
+    override val appAction: AppAction get() =
         actionSpec
             .convertPropertyToProto(property)
             .toBuilder()
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 3779b5c..07ae86c 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
@@ -18,9 +18,9 @@
 
 import androidx.annotation.GuardedBy
 import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
 import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
 import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
+import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
 import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
 import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
 import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
@@ -30,6 +30,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancel
 import kotlinx.coroutines.launch
 
 internal class TaskCapabilitySession<
@@ -58,6 +59,7 @@
     override fun destroy() {
         // TODO(b/270751989): cancel current processing request immediately
         this.sessionOrchestrator.terminate()
+        scope.cancel()
     }
 
     override val uiHandle: Any = externalSession
@@ -71,16 +73,17 @@
             ArgumentsT,
             OutputT,
             ConfirmationT,
-        > =
+            > =
         TaskOrchestrator(
             sessionId,
             actionSpec,
             appAction,
             taskHandler,
             externalSession,
+            scope,
         )
-
-    @GuardedBy("requestLock") private var pendingAssistantRequest: AssistantUpdateRequest? = null
+    @GuardedBy("requestLock")
+    private var pendingAssistantRequest: AssistantUpdateRequest? = null
     @GuardedBy("requestLock") private var pendingTouchEventRequest: TouchEventUpdateRequest? = null
 
     override fun execute(argumentsWrapper: ArgumentsWrapper, callback: CallbackInternal) {
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 8d00b16..b0e1396 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
@@ -27,12 +27,12 @@
 import androidx.appactions.interaction.capabilities.core.impl.UiHandleRegistry
 import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
 import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
 import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.InvalidResolverException
 import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingEntityConverterException
 import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingRequiredArgException
 import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingSearchActionConverterException
+import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger
+import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
 import androidx.appactions.interaction.proto.AppActionsContext
 import androidx.appactions.interaction.proto.CurrentValue
 import androidx.appactions.interaction.proto.FulfillmentRequest
@@ -42,7 +42,8 @@
 import java.util.concurrent.locks.ReentrantReadWriteLock
 import kotlin.concurrent.read
 import kotlin.concurrent.write
-import kotlin.jvm.Throws
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.isActive
 
 /**
  * TaskOrchestrator is responsible for holding session state, and processing assistant / manual
@@ -59,6 +60,7 @@
     private val appAction: AppActionsContext.AppAction,
     private val taskHandler: TaskHandler<ConfirmationT>,
     private val externalSession: BaseExecutionSession<ArgumentsT, OutputT>,
+    private val scope: CoroutineScope,
 ) {
     /** This enum describes the current status of the TaskOrchestrator. */
     internal enum class Status {
@@ -348,6 +350,9 @@
     ) {
         var currentResult = SlotProcessingResult(true, emptyList())
         for ((name, fulfillmentValues) in fulfillmentValuesMap) {
+            if (!scope.isActive) {
+                break
+            }
             currentResult =
                 maybeProcessSlotAndUpdateCurrentValues(currentResult, name, fulfillmentValues)
         }
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
index a8b66c3..b6d8e63 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
@@ -17,9 +17,9 @@
 package androidx.appactions.interaction.capabilities.core.impl
 
 import android.util.SizeF
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutor
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutorAsync
-import androidx.appactions.interaction.capabilities.core.toCapabilityExecutor
+import androidx.appactions.interaction.capabilities.core.ExecutionCallback
+import androidx.appactions.interaction.capabilities.core.ExecutionCallbackAsync
+import androidx.appactions.interaction.capabilities.core.toExecutionCallback
 import androidx.appactions.interaction.capabilities.core.ExecutionResult
 import androidx.appactions.interaction.capabilities.core.HostProperties
 import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
@@ -35,10 +35,13 @@
 import androidx.appactions.interaction.capabilities.core.testing.spec.Arguments
 import androidx.appactions.interaction.capabilities.core.testing.spec.Output
 import androidx.appactions.interaction.capabilities.core.testing.spec.Properties
+import androidx.appactions.interaction.proto.AppActionsContext.AppAction
+import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
 import androidx.appactions.interaction.proto.FulfillmentResponse
 import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
 import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
 import androidx.appactions.interaction.proto.ParamValue
+import androidx.appactions.interaction.proto.TaskInfo
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.runBlocking
@@ -54,9 +57,66 @@
     private val fakeSessionId = "fakeSessionId"
 
     @Test
+    fun appAction_computedProperty() {
+        val mutableEntityList = mutableListOf<Entity>()
+        val capability = SingleTurnCapabilityImpl(
+            id = "capabilityId",
+            actionSpec = ACTION_SPEC,
+            property = Properties.newBuilder()
+                .setRequiredEntityField(
+                    Property.Builder<Entity>().setPossibleValueSupplier(
+                        mutableEntityList::toList
+                    ).build()
+                )
+                .build(),
+            executionCallback = ExecutionCallback<Arguments, Output> {
+                ExecutionResult.Builder<Output>().build()
+            }
+        )
+        mutableEntityList.add(Entity.Builder().setName("entity1").build())
+
+        assertThat(capability.appAction).isEqualTo(
+            AppAction.newBuilder()
+                .setIdentifier("capabilityId")
+                .setName("actions.intent.TEST")
+                .addParams(
+                    IntentParameter.newBuilder()
+                        .setName("requiredEntity")
+                        .addPossibleEntities(
+                            androidx.appactions.interaction.proto.Entity.newBuilder()
+                                .setName("entity1")
+                        )
+                )
+                .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
+                .build()
+        )
+
+        mutableEntityList.add(Entity.Builder().setName("entity2").build())
+        assertThat(capability.appAction).isEqualTo(
+            AppAction.newBuilder()
+                .setIdentifier("capabilityId")
+                .setName("actions.intent.TEST")
+                .addParams(
+                    IntentParameter.newBuilder()
+                        .setName("requiredEntity")
+                        .addPossibleEntities(
+                            androidx.appactions.interaction.proto.Entity.newBuilder()
+                                .setName("entity1")
+                        )
+                        .addPossibleEntities(
+                            androidx.appactions.interaction.proto.Entity.newBuilder()
+                                .setName("entity2")
+                        )
+                )
+                .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
+                .build()
+        )
+    }
+
+    @Test
     fun oneShotCapability_successWithOutput() {
-        val capabilityExecutor =
-            CapabilityExecutor<Arguments, Output> {
+        val executionCallback =
+            ExecutionCallback<Arguments, Output> {
                 ExecutionResult.Builder<Output>()
                     .setOutput(
                         Output.builder().setOptionalStringField("stringOutput").build()
@@ -74,7 +134,7 @@
                     )
                     .setOptionalStringField(Property.prohibited())
                     .build(),
-                capabilityExecutor = capabilityExecutor
+                executionCallback = executionCallback
             )
 
         val capabilitySession = capability.createSession(fakeSessionId, hostProperties)
@@ -119,8 +179,8 @@
 
     @Test
     fun oneShotCapability_failure() {
-        val capabilityExecutor =
-            CapabilityExecutor<Arguments, Output> { throw IllegalStateException("") }
+        val executionCallback =
+            ExecutionCallback<Arguments, Output> { throw IllegalStateException("") }
         val capability =
             SingleTurnCapabilityImpl(
                 id = "capabilityId",
@@ -132,7 +192,7 @@
                     )
                     .setOptionalStringField(Property.prohibited())
                     .build(),
-                capabilityExecutor = capabilityExecutor
+                executionCallback = executionCallback
             )
 
         val capabilitySession = capability.createSession(fakeSessionId, hostProperties)
@@ -153,9 +213,9 @@
     }
 
     @Test
-    fun oneShotSession_uiHandle_withCapabilityExecutor() {
-        val capabilityExecutor =
-            CapabilityExecutor<Arguments, Output> { ExecutionResult.Builder<Output>().build() }
+    fun oneShotSession_uiHandle_withExecutionCallback() {
+        val executionCallback =
+            ExecutionCallback<Arguments, Output> { ExecutionResult.Builder<Output>().build() }
         val capability =
             SingleTurnCapabilityImpl(
                 id = "capabilityId",
@@ -166,16 +226,16 @@
                         Property.Builder<Entity>().build()
                     )
                     .build(),
-                capabilityExecutor = capabilityExecutor
+                executionCallback = executionCallback
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
-        assertThat(session.uiHandle).isSameInstanceAs(capabilityExecutor)
+        assertThat(session.uiHandle).isSameInstanceAs(executionCallback)
     }
 
     @Test
-    fun oneShotSession_uiHandle_withCapabilityExecutorAsync() {
-        val capabilityExecutorAsync =
-            CapabilityExecutorAsync<Arguments, Output> {
+    fun oneShotSession_uiHandle_withExecutionCallbackAsync() {
+        val executionCallbackAsync =
+            ExecutionCallbackAsync<Arguments, Output> {
                 Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
             }
         val capability =
@@ -188,10 +248,10 @@
                         Property.Builder<Entity>().build()
                     )
                     .build(),
-                capabilityExecutor = capabilityExecutorAsync.toCapabilityExecutor()
+                executionCallback = executionCallbackAsync.toExecutionCallback()
             )
         val session = capability.createSession(fakeSessionId, hostProperties)
-        assertThat(session.uiHandle).isSameInstanceAs(capabilityExecutorAsync)
+        assertThat(session.uiHandle).isSameInstanceAs(executionCallbackAsync)
     }
 
     @Test
@@ -199,7 +259,7 @@
         val executionResultChannel = Channel<ExecutionResult<Output>>()
         val argumentChannel = Channel<Arguments>()
 
-        val capabilityExecutor = CapabilityExecutor<Arguments, Output> {
+        val executionCallback = ExecutionCallback<Arguments, Output> {
             argumentChannel.send(it)
             executionResultChannel.receive()
         }
@@ -209,7 +269,7 @@
             property = Properties.newBuilder().setRequiredEntityField(
                 Property.Builder<Entity>().build()
             ).build(),
-            capabilityExecutor = capabilityExecutor
+            executionCallback = executionCallback
         )
         val session1 = capability.createSession("session1", hostProperties)
         val session2 = capability.createSession("session2", hostProperties)
@@ -236,7 +296,7 @@
             callbackInternal2
         )
 
-        // verify CapabilityExecutor receives 1st request.
+        // verify ExecutionCallback receives 1st request.
         assertThat(argumentChannel.receive()).isEqualTo(
             Arguments.newBuilder().setOptionalStringField("string value 1").build()
         )
@@ -266,6 +326,13 @@
                 .setDescriptor(Properties::class.java)
                 .setArguments(Arguments::class.java, Arguments::newBuilder)
                 .setOutput(Output::class.java)
+                .bindParameter(
+                    "requiredEntity",
+                    Properties::requiredEntityField,
+                    Arguments.Builder::setRequiredEntityField,
+                    TypeConverters.ENTITY_PARAM_VALUE_CONVERTER,
+                    TypeConverters.ENTITY_ENTITY_CONVERTER
+                )
                 .bindOptionalParameter(
                     "optionalString",
                     Properties::optionalStringField,
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java
index 074820d..3deb2a0 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java
@@ -490,16 +490,13 @@
     }
 
     @Test
-    public void toLocalDate_success() throws Exception {
-        List<ParamValue> input =
-                Collections.singletonList(
-                        ParamValue.newBuilder().setStringValue("2018-06-17").build());
+    public void localDate_success() throws Exception {
+        ParamValueConverter<LocalDate> converter = TypeConverters.LOCAL_DATE_PARAM_VALUE_CONVERTER;
+        ParamValue paramValue = ParamValue.newBuilder().setStringValue("2018-06-17").build();
+        LocalDate localDate = LocalDate.of(2018, 6, 17);
 
-        assertThat(
-                SlotTypeConverter.ofSingular(
-                                TypeConverters.LOCAL_DATE_PARAM_VALUE_CONVERTER)
-                        .convert(input))
-                .isEqualTo(LocalDate.of(2018, 6, 17));
+        assertThat(converter.fromParamValue(paramValue)).isEqualTo(localDate);
+        assertThat(converter.toParamValue(localDate)).isEqualTo(paramValue);
     }
 
     @Test
@@ -537,16 +534,13 @@
     }
 
     @Test
-    public void toLocalTime_success() throws Exception {
-        List<ParamValue> input =
-                Collections.singletonList(
-                        ParamValue.newBuilder().setStringValue("15:10:05").build());
+    public void localTime_success() throws Exception {
+        ParamValueConverter<LocalTime> converter = TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER;
+        ParamValue paramValue = ParamValue.newBuilder().setStringValue("15:10:05").build();
+        LocalTime localTime = LocalTime.of(15, 10, 5);
 
-        assertThat(
-                SlotTypeConverter.ofSingular(
-                                TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER)
-                        .convert(input))
-                .isEqualTo(LocalTime.of(15, 10, 5));
+        assertThat(converter.fromParamValue(paramValue)).isEqualTo(localTime);
+        assertThat(converter.toParamValue(localTime)).isEqualTo(paramValue);
     }
 
     @Test
@@ -583,15 +577,13 @@
     }
 
     @Test
-    public void toZoneId_success() throws Exception {
-        List<ParamValue> input =
-                Collections.singletonList(
-                        ParamValue.newBuilder().setStringValue("America/New_York").build());
+    public void zoneId_success() throws Exception {
+        ParamValueConverter<ZoneId> converter = TypeConverters.ZONE_ID_PARAM_VALUE_CONVERTER;
+        ParamValue paramValue = ParamValue.newBuilder().setStringValue("America/New_York").build();
+        ZoneId zoneId = ZoneId.of("America/New_York");
 
-        assertThat(
-                SlotTypeConverter.ofSingular(TypeConverters.ZONE_ID_PARAM_VALUE_CONVERTER)
-                        .convert(input))
-                .isEqualTo(ZoneId.of("America/New_York"));
+        assertThat(converter.fromParamValue(paramValue)).isEqualTo(zoneId);
+        assertThat(converter.toParamValue(zoneId)).isEqualTo(paramValue);
     }
 
     @Test
@@ -627,16 +619,15 @@
     }
 
     @Test
-    public void toZonedDateTime_fromList() throws Exception {
-        List<ParamValue> input =
-                Collections.singletonList(
-                        ParamValue.newBuilder().setStringValue("2018-06-17T15:10:05Z").build());
+    public void zonedDateTime_success() throws Exception {
+        ParamValueConverter<ZonedDateTime> converter =
+                TypeConverters.ZONED_DATETIME_PARAM_VALUE_CONVERTER;
+        ParamValue paramValue =
+                ParamValue.newBuilder().setStringValue("2018-06-17T15:10:05Z").build();
+        ZonedDateTime zonedDateTime = ZonedDateTime.of(2018, 6, 17, 15, 10, 5, 0, ZoneOffset.UTC);
 
-        assertThat(
-                SlotTypeConverter.ofSingular(
-                                TypeConverters.ZONED_DATETIME_PARAM_VALUE_CONVERTER)
-                        .convert(input))
-                .isEqualTo(ZonedDateTime.of(2018, 6, 17, 15, 10, 5, 0, ZoneOffset.UTC));
+        assertThat(converter.fromParamValue(paramValue)).isEqualTo(zonedDateTime);
+        assertThat(converter.toParamValue(zonedDateTime)).isEqualTo(paramValue);
     }
 
     @Test
@@ -678,15 +669,14 @@
     }
 
     @Test
-    public void toDuration_success() throws Exception {
-        List<ParamValue> input =
-                Collections.singletonList(ParamValue.newBuilder().setStringValue("PT5M").build());
+    public void duration_success() throws Exception {
+        ParamValueConverter<Duration> converter = TypeConverters.DURATION_PARAM_VALUE_CONVERTER;
+        ParamValue paramValue =
+                ParamValue.newBuilder().setStringValue("PT5M").build();
+        Duration duration = Duration.ofMinutes(5);
 
-        Duration convertedDuration =
-                SlotTypeConverter.ofSingular(TypeConverters.DURATION_PARAM_VALUE_CONVERTER)
-                        .convert(input);
-
-        assertThat(convertedDuration).isEqualTo(Duration.ofMinutes(5));
+        assertThat(converter.fromParamValue(paramValue)).isEqualTo(duration);
+        assertThat(converter.toParamValue(duration)).isEqualTo(paramValue);
     }
 
     @Test
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 8c6546b..d4c4273 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
@@ -103,7 +103,7 @@
     private val fakeSessionId = "fakeSessionId"
 
     @Test
-    fun getAppAction_smokeTest() {
+    fun appAction_smokeTest() {
         assertThat(capability.appAction)
             .isEqualTo(
                 AppAction.newBuilder()
@@ -120,6 +120,68 @@
     }
 
     @Test
+    fun appAction_computedProperty() {
+        val mutableEntityList = mutableListOf<
+            androidx.appactions.interaction.capabilities.core.properties.Entity
+        >()
+        val capability = createCapability<EmptyTaskUpdater>(
+            Properties.newBuilder()
+                .setRequiredEntityField(
+                    Property.Builder<
+                        androidx.appactions.interaction.capabilities.core.properties.Entity
+                    >().setPossibleValueSupplier(
+                        mutableEntityList::toList
+                    ).build()
+                )
+                .build(),
+            sessionFactory =
+            {
+                object : ExecutionSession {
+                    override fun onExecuteAsync(arguments: Arguments) =
+                        Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
+                }
+            },
+            sessionBridge = { TaskHandler.Builder<Confirmation>().build() },
+            sessionUpdaterSupplier = ::EmptyTaskUpdater,
+        )
+        mutableEntityList.add(
+            androidx.appactions.interaction.capabilities.core.properties.Entity.Builder()
+                .setName("entity1").build()
+        )
+
+        assertThat(capability.appAction).isEqualTo(
+            AppAction.newBuilder()
+                .setIdentifier("id")
+                .setName("actions.intent.TEST")
+                .addParams(
+                    IntentParameter.newBuilder()
+                        .setName("required")
+                        .addPossibleEntities(Entity.newBuilder().setName("entity1"))
+                )
+                .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(true))
+                .build()
+        )
+
+        mutableEntityList.add(
+            androidx.appactions.interaction.capabilities.core.properties.Entity.Builder()
+                .setName("entity2").build()
+        )
+        assertThat(capability.appAction).isEqualTo(
+            AppAction.newBuilder()
+                .setIdentifier("id")
+                .setName("actions.intent.TEST")
+                .addParams(
+                    IntentParameter.newBuilder()
+                        .setName("required")
+                        .addPossibleEntities(Entity.newBuilder().setName("entity1"))
+                        .addPossibleEntities(Entity.newBuilder().setName("entity2"))
+                )
+                .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(true))
+                .build()
+        )
+    }
+
+    @Test
     fun capabilitySession_getUiHandle() {
         val externalSession = object : ExecutionSession {}
         val capability =
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt
index 46494c3..39c7d77 100644
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt
+++ b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt
@@ -16,7 +16,7 @@
 
 package androidx.appactions.interaction.capabilities.testing.internal
 
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutorAsync
+import androidx.appactions.interaction.capabilities.core.ExecutionCallbackAsync
 import androidx.appactions.interaction.capabilities.core.ExecutionResult
 import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
 import kotlinx.coroutines.Deferred
@@ -30,9 +30,9 @@
     // use this timeout for waiting an arbitrary period of time.
     const val BLOCKING_TIMEOUT = 300L
 
-    fun <ArgumentsT, OutputT> createFakeCapabilityExecutor():
-        CapabilityExecutorAsync<ArgumentsT, OutputT> {
-        return CapabilityExecutorAsync { _: ArgumentsT ->
+    fun <ArgumentsT, OutputT> createFakeExecutionCallback():
+        ExecutionCallbackAsync<ArgumentsT, OutputT> {
+        return ExecutionCallbackAsync { _: ArgumentsT ->
             Futures.immediateFuture(
                 ExecutionResult.Builder<OutputT>().build()
             )
diff --git a/appactions/interaction/interaction-service-proto/build.gradle b/appactions/interaction/interaction-service-proto/build.gradle
index 38a00154..884a1aa 100644
--- a/appactions/interaction/interaction-service-proto/build.gradle
+++ b/appactions/interaction/interaction-service-proto/build.gradle
@@ -47,6 +47,10 @@
     compileOnly("androidx.annotation:annotation:1.1.0")
 }
 
+jar {
+    exclude "**/*.proto"
+}
+
 protobuf {
     protoc {
         artifact = libs.protobufCompiler.get()
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
index 8c7a81f..1774fa6 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
@@ -18,7 +18,7 @@
 package androidx.appactions.interaction.service
 
 import androidx.annotation.GuardedBy
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutor
+import androidx.appactions.interaction.capabilities.core.ExecutionCallback
 import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
 import androidx.appactions.interaction.capabilities.core.impl.UiHandleRegistry
 import androidx.appactions.interaction.service.UiSessions.removeUiCache
@@ -70,8 +70,8 @@
         UiHandleRegistry.getSessionIdFromUiHandle(this)!!
     ).updateUiInternal(uiResponse)
 
-/** Return a UI associated with this [CapabilityExecutor]. */
-fun CapabilityExecutor<*, *>.updateUi(uiResponse: UiResponse) =
+/** Return a UI associated with this [ExecutionCallback]. */
+fun ExecutionCallback<*, *>.updateUi(uiResponse: UiResponse) =
     UiSessions.getOrCreateUiCache(
         UiHandleRegistry.getSessionIdFromUiHandle(this)!!
     ).updateUiInternal(uiResponse)
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
index e9e60c5..d72a575 100644
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
+++ b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
@@ -19,7 +19,7 @@
 import android.content.Context
 import android.util.SizeF
 import android.widget.RemoteViews
-import androidx.appactions.interaction.capabilities.core.CapabilityExecutor
+import androidx.appactions.interaction.capabilities.core.ExecutionCallback
 import androidx.appactions.interaction.capabilities.core.ExecutionResult
 import androidx.appactions.interaction.capabilities.core.HostProperties
 import androidx.appactions.interaction.capabilities.core.ExecutionSessionFactory
@@ -252,11 +252,11 @@
     }
 
     @Test
-    fun capabilityExecutor_hasUpdateUiExtension() {
+    fun executionCallback_hasUpdateUiExtension() {
         assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
         val oneShotCapability = FakeCapability.CapabilityBuilder().setId(
             "oneShotCapability",
-        ).setExecutor(object : CapabilityExecutor<Arguments, Output> {
+        ).setExecutionCallback(object : ExecutionCallback<Arguments, Output> {
             override suspend fun onExecute(arguments: Arguments): ExecutionResult<Output> {
                 this.updateUi(remoteViewsUiResponse)
                 return ExecutionResult.Builder<Output>().build()
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java
index bfb32b8..b48c66c 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java
@@ -18,7 +18,6 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
-import static androidx.annotation.RestrictTo.Scope.TESTS;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
@@ -56,6 +55,7 @@
 import androidx.annotation.RestrictTo;
 import androidx.annotation.StringRes;
 import androidx.annotation.StyleRes;
+import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.R;
 import androidx.appcompat.app.ActionBar;
 import androidx.appcompat.content.res.AppCompatResources;
@@ -1607,7 +1607,7 @@
      * Returns the navigation button view.
      *
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @Nullable
     View getNavButtonView() {
         return mNavButtonView;
@@ -2418,7 +2418,7 @@
 
     /**
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     @Nullable
     final TextView getTitleTextView() {
         return mTitleTextView;
@@ -2426,7 +2426,7 @@
 
     /**
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     @Nullable
     final TextView getSubtitleTextView() {
         return mSubtitleTextView;
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
index 8b9c181..81151eb 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
@@ -19,6 +19,7 @@
 import android.os.Bundle
 import android.util.Log
 import androidx.annotation.RestrictTo
+import androidx.annotation.VisibleForTesting
 import androidx.test.platform.app.InstrumentationRegistry
 
 /**
@@ -26,13 +27,13 @@
  *
  * @hide
  */
-@RestrictTo(RestrictTo.Scope.TESTS)
+@VisibleForTesting
 public var argumentSource: Bundle? = null
 
 /**
  * Allows tests to override profiler
  */
-@RestrictTo(RestrictTo.Scope.TESTS)
+@VisibleForTesting
 internal var profilerOverride: Profiler? = null
 
 /**
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
index 9e372d7..7028319 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
@@ -20,7 +20,7 @@
 import android.os.Debug
 import android.util.Log
 import androidx.annotation.RequiresApi
-import androidx.annotation.RestrictTo
+import androidx.annotation.VisibleForTesting
 import androidx.benchmark.BenchmarkState.Companion.TAG
 import androidx.benchmark.Outputs.dateToFileName
 import androidx.benchmark.simpleperf.ProfileSession
@@ -132,7 +132,7 @@
 }
 
 internal object StackSamplingLegacy : Profiler() {
-    @get:RestrictTo(RestrictTo.Scope.TESTS)
+    @get:VisibleForTesting
     var isRunning = false
 
     override fun start(traceUniqueName: String): ResultFile {
diff --git a/benchmark/benchmark-macro/lint-baseline.xml b/benchmark/benchmark-macro/lint-baseline.xml
index c22cb1c..fb8dd8f 100644
--- a/benchmark/benchmark-macro/lint-baseline.xml
+++ b/benchmark/benchmark-macro/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.0.0-beta03" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.0-beta03)" variant="all" version="8.0.0-beta03">
+<issues format="6" by="lint 8.1.0-alpha11" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0-alpha11)" variant="all" version="8.1.0-alpha11">
 
     <issue
         id="BanThreadSleep"
@@ -112,15 +112,6 @@
     <issue
         id="BanThreadSleep"
         message="Uses Thread.sleep()"
-        errorLine1="            Thread.sleep(5)"
-        errorLine2="                   ~~~~~">
-        <location
-            file="src/main/java/androidx/benchmark/macro/perfetto/server/PerfettoHttpServer.kt"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
         errorLine1="                Thread.sleep(500)"
         errorLine2="                       ~~~~~">
         <location
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/FrameTimingQueryTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/FrameTimingQueryTest.kt
index 66ed720..6dfc931 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/FrameTimingQueryTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/FrameTimingQueryTest.kt
@@ -20,6 +20,7 @@
 import androidx.benchmark.macro.perfetto.FrameTimingQuery.SubMetric.FrameDurationCpuNs
 import androidx.benchmark.macro.perfetto.FrameTimingQuery.SubMetric.FrameDurationUiNs
 import androidx.benchmark.macro.perfetto.FrameTimingQuery.SubMetric.FrameOverrunNs
+import androidx.benchmark.macro.perfetto.FrameTimingQuery.getFrameSubMetrics
 import androidx.benchmark.perfetto.PerfettoHelper.Companion.isAbiSupported
 import androidx.benchmark.perfetto.PerfettoTraceProcessor
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -40,11 +41,11 @@
         val frameSubMetrics = PerfettoTraceProcessor.runSingleSessionServer(
             traceFile.absolutePath
         ) {
-            FrameTimingQuery.getFrameSubMetrics(
+            FrameTimingQuery.getFrameData(
                 session = this,
                 captureApiLevel = 28,
                 packageName = "androidx.benchmark.integration.macrobenchmark.target"
-            )
+            ).getFrameSubMetrics(captureApiLevel = 28)
         }
 
         assertEquals(
@@ -72,11 +73,11 @@
         val frameSubMetrics = PerfettoTraceProcessor.runSingleSessionServer(
             traceFile.absolutePath
         ) {
-            FrameTimingQuery.getFrameSubMetrics(
+            FrameTimingQuery.getFrameData(
                 session = this,
                 captureApiLevel = 31,
                 packageName = "androidx.benchmark.integration.macrobenchmark.target"
-            )
+            ).getFrameSubMetrics(captureApiLevel = 31)
         }
 
         assertEquals(
@@ -95,4 +96,61 @@
             message = "Expect same number of frames for each metric"
         )
     }
+
+    /**
+     * This validates that we're able to see all frames, even if expected/actual frame IDs don't
+     * match UI thread and Renderthread (b/279088460)
+     */
+    @MediumTest
+    @Test
+    fun fixedTrace33_mismatchExpectedActualFrameIds() {
+        assumeTrue(isAbiSupported())
+        val traceFile =
+            createTempFileFromAsset("api33_motionlayout_messagejson", ".perfetto-trace")
+
+        val frameData = PerfettoTraceProcessor.runSingleSessionServer(
+            traceFile.absolutePath
+        ) {
+            FrameTimingQuery.getFrameData(
+                session = this,
+                captureApiLevel = 33,
+                packageName = "androidx.constraintlayout.compose.integration.macrobenchmark.target"
+            )
+        }
+
+        // although there are 58 frames in the trace, the last 4
+        // don't have associated complete expected/actual events
+        assertEquals(54, frameData.size)
+
+        // first frame, with matching IDs
+        frameData.single {
+            it.rtSlice.frameId == 1370854
+        }.run {
+            assertEquals(1370854, this.uiSlice.frameId)
+            assertEquals(1370854, this.expectedSlice!!.frameId)
+            assertEquals(1370854, this.actualSlice!!.frameId)
+        }
+
+        // second frame, where IDs don't match
+        frameData.single {
+            it.rtSlice.frameId == 1370869
+        }.run {
+            assertEquals(1370869, this.uiSlice.frameId) // matches
+            assertEquals(1370876, this.expectedSlice!!.frameId) // doesn't match!
+            assertEquals(1370876, this.actualSlice!!.frameId) // doesn't match!
+        }
+
+        assertEquals(
+            // Note: it's correct for UI to be > CPU in cases below,
+            // since UI is be sleeping after RT is done
+            expected = mapOf(
+                FrameDurationCpuNs to listOf(7304479L, 7567188L, 8064897L, 8434115L),
+                FrameDurationUiNs to listOf(4253646L, 7592761L, 8088855L, 8461876L),
+                FrameOverrunNs to listOf(-9009770L, -12199949L, -11299378L, -11708522L)
+            ),
+            actual = frameData.getFrameSubMetrics(captureApiLevel = 33).mapValues {
+                it.value.subList(0, 4)
+            }
+        )
+    }
 }
\ No newline at end of file
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/perfetto/PerfettoTraceProcessorTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/perfetto/PerfettoTraceProcessorTest.kt
index ff8666e..385b460 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/perfetto/PerfettoTraceProcessorTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/perfetto/PerfettoTraceProcessorTest.kt
@@ -16,12 +16,14 @@
 
 package androidx.benchmark.perfetto
 
+import androidx.benchmark.Outputs
 import androidx.benchmark.Shell
 import androidx.benchmark.macro.createTempFileFromAsset
 import androidx.benchmark.perfetto.PerfettoHelper.Companion.isAbiSupported
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
+import java.io.File
 import java.net.ConnectException
 import java.net.HttpURLConnection
 import java.net.URL
@@ -250,4 +252,26 @@
         // Check server is not running
         assertTrue(!isRunning())
     }
+
+    @Test
+    fun parseLongTrace() {
+        val traceFile = File
+            .createTempFile("long_trace", ".trace", Outputs.dirUsableByAppAndShell)
+            .apply {
+                var length = 0L
+                val out = outputStream()
+                while (length < 70 * 1024 * 1024) {
+                    length += InstrumentationRegistry
+                        .getInstrumentation()
+                        .context
+                        .assets
+                        .open("api31_startup_cold.perfetto-trace")
+                        .copyTo(out)
+                }
+            }
+        PerfettoTraceProcessor.runSingleSessionServer(traceFile.absolutePath) {
+            // This would throw an exception if there is an error in the parsing.
+            getTraceMetrics("android_startup")
+        }
+    }
 }
\ No newline at end of file
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
index d839e8f..d19339e 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
@@ -302,18 +302,14 @@
 private fun extractProfile(packageName: String): String {
 
     val dumpCommand = "pm dump-profiles --dump-classes-and-methods $packageName"
-    if (BuildCompat.isAtLeastU()) {
-        // On api 34 this will produce an output like:
-        // Profile saved to '/data/misc/profman/<PACKAGE_NAME>-primary.prof.txt'
-        val stdout = Shell.executeScriptCaptureStdout(dumpCommand).trim()
-        val expected = "Profile saved to '/data/misc/profman/$packageName-primary.prof.txt'"
-        check(stdout == expected) {
-            "Expected `pm dump-profiles` stdout to be $expected but was $stdout"
-        }
-    } else {
-        // On api 33 and below this command does not produce any output
-        Shell.executeScriptSilent(dumpCommand)
+    val stdout = Shell.executeScriptCaptureStdout(dumpCommand).trim()
+    val expected = "Profile saved to '/data/misc/profman/$packageName-primary.prof.txt'"
+
+    // Output of profman was empty in previous version and can be `expected` on newer versions.
+    check(stdout.isBlank() || stdout == expected) {
+        "Expected `pm dump-profiles` stdout to be either black or `$expected` but was $stdout"
     }
+
     val fileName = "$packageName-primary.prof.txt"
     Shell.executeScriptSilent(
         "mv /data/misc/profman/$fileName ${Outputs.dirUsableByAppAndShell}/"
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
index f60a946..8a73eea 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
@@ -101,8 +101,8 @@
                         val output = Shell.executeScriptCaptureStdout(
                             "cmd package compile --reset $packageName"
                         )
-                        check(output.trim() == "Success") {
-                            "Unable to recompile $packageName ($output)"
+                        check(output.trim() == "Success" || output.contains("PERFORMED")) {
+                            "Unable to recompile $packageName (out=$output)"
                         }
                     } else {
                         // User builds pre-U. Kick off a full uninstall-reinstall
@@ -154,8 +154,8 @@
                 // correctly installed. (b/231294733)
                 output = Shell.executeScriptCaptureStdout("pm install -t $tempApkPathsString")
 
-                check(output.trim() == "Success") {
-                    "Unable to install $packageName ($output)"
+                check(output.trim() == "Success" || output.contains("PERFORMED")) {
+                    "Unable to install $packageName (out=$output)"
                 }
             } finally {
                 // Cleanup the temporary APK
@@ -433,7 +433,9 @@
             val stdout = Shell.executeScriptCaptureStdout(
                 "cmd package compile -f -m $compileArgument $packageName"
             )
-            check(stdout.trim() == "Success")
+            check(stdout.trim() == "Success" || stdout.contains("PERFORMED")) {
+                "Failed to compile (out=$stdout)"
+            }
         }
     }
 }
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt
index 6c6c458..36241de 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt
@@ -28,6 +28,7 @@
 import androidx.benchmark.macro.perfetto.BatteryDischargeQuery
 import androidx.benchmark.macro.perfetto.FrameTimingQuery
 import androidx.benchmark.macro.perfetto.FrameTimingQuery.SubMetric
+import androidx.benchmark.macro.perfetto.FrameTimingQuery.getFrameSubMetrics
 import androidx.benchmark.macro.perfetto.MemoryCountersQuery
 import androidx.benchmark.macro.perfetto.PowerQuery
 import androidx.benchmark.macro.perfetto.StartupTimingQuery
@@ -193,11 +194,12 @@
         captureInfo: CaptureInfo,
         traceSession: PerfettoTraceProcessor.Session
     ): List<Measurement> {
-        return FrameTimingQuery.getFrameSubMetrics(
+        return FrameTimingQuery.getFrameData(
             session = traceSession,
             captureApiLevel = Build.VERSION.SDK_INT,
             packageName = captureInfo.targetPackageName
         )
+            .getFrameSubMetrics(Build.VERSION.SDK_INT)
             .filterKeys { it == SubMetric.FrameDurationCpuNs || it == SubMetric.FrameOverrunNs }
             .map {
                 Measurement(
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/FrameTimingQuery.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/FrameTimingQuery.kt
index ac49d29..d0446bc 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/FrameTimingQuery.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/FrameTimingQuery.kt
@@ -83,7 +83,7 @@
      *
      * Nullable slices are always present on API 31+
      */
-    private class FrameData(
+    internal class FrameData(
         val uiSlice: Slice,
         val rtSlice: Slice,
         val expectedSlice: Slice?,
@@ -93,7 +93,10 @@
             return when (subMetric) {
                 SubMetric.FrameDurationCpuNs -> rtSlice.endTs - uiSlice.ts
                 SubMetric.FrameDurationUiNs -> uiSlice.dur
-                SubMetric.FrameOverrunNs -> actualSlice!!.endTs - expectedSlice!!.endTs
+                SubMetric.FrameOverrunNs -> {
+                    // workaround b/279088460, where actual slice ends too early
+                    maxOf(actualSlice!!.endTs, rtSlice.endTs) - expectedSlice!!.endTs
+                }
             }
         }
         companion object {
@@ -141,11 +144,11 @@
         }
     }
 
-    fun getFrameSubMetrics(
+    internal fun getFrameData(
         session: PerfettoTraceProcessor.Session,
         captureApiLevel: Int,
         packageName: String,
-    ): Map<SubMetric, List<Long>> {
+    ): List<FrameData> {
         val queryResultIterator = session.query(
             query = getFullQuery(packageName)
         )
@@ -173,7 +176,7 @@
         val expectedSlices = groupedData.getOrElse(FrameSliceType.Expected) { listOf() }
 
         if (uiSlices.isEmpty()) {
-            return emptyMap()
+            return emptyList()
         }
 
         // check data looks reasonable
@@ -181,17 +184,40 @@
         require(actualSlices.isEmpty() == newSlicesShouldBeEmpty)
         require(expectedSlices.isEmpty() == newSlicesShouldBeEmpty)
 
-        val frameData = if (captureApiLevel >= 31) {
+        return if (captureApiLevel >= 31) {
             // No slice should be missing a frameId
             require(slices.none { it.frameId == null })
+
+            val actualSlicesPool = actualSlices.toMutableList()
             rtSlices.mapNotNull { rtSlice ->
                 val frameId = rtSlice.frameId!!
-                FrameData.tryCreate31(
-                    uiSlice = uiSlices.binarySearchFrameId(frameId),
-                    rtSlice = rtSlice,
-                    expectedSlice = expectedSlices.binarySearchFrameId(frameId),
-                    actualSlice = actualSlices.binarySearchFrameId(frameId)
-                )
+
+                val uiSlice = uiSlices.binarySearchFrameId(frameId)
+
+                // Ideally, we'd rely on frameIds, but these can fall out of sync due to b/279088460
+                //     expectedSlice = expectedSlices.binarySearchFrameId(frameId),
+                //     actualSlice = actualSlices.binarySearchFrameId(frameId)
+                // A pool of actual slices is used to prevent incorrect duplicate mapping. At the
+                //     end of the trace, the synthetic expect/actual slices may be missing even if
+                //     the complete end of frame is present, and we want to discard those. This
+                //     doesn't happen at front of trace, since we find actuals from the end.
+                if (uiSlice != null) {
+                    // Use fixed offset since synthetic tracepoint for actual may start after the
+                    // actual UI slice (have observed 2us in practice)
+                    val actualSlice = actualSlicesPool.lastOrNull { it.ts < uiSlice.ts + 50_000 }
+                    actualSlicesPool.remove(actualSlice)
+                    val expectedSlice = actualSlice?.frameId?.run {
+                        expectedSlices.binarySearchFrameId(this)
+                    }
+                    FrameData.tryCreate31(
+                        uiSlice = uiSlice,
+                        rtSlice = rtSlice,
+                        expectedSlice = expectedSlice,
+                        actualSlice = actualSlice
+                    )
+                } else {
+                    null
+                }
             }
         } else {
             require(slices.none { it.frameId != null })
@@ -202,11 +228,13 @@
                 )
             }
         }
+    }
 
+    fun List<FrameData>.getFrameSubMetrics(captureApiLevel: Int): Map<SubMetric, List<Long>> {
         return SubMetric.values()
             .filter { it.supportedOnApiLevel(captureApiLevel) }
             .associateWith { subMetric ->
-                frameData.map { frame -> frame.get(subMetric) }
+                map { frame -> frame.get(subMetric) }
             }
     }
 }
\ No newline at end of file
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/server/PerfettoHttpServer.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/server/PerfettoHttpServer.kt
index de174db..e62dbec 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/server/PerfettoHttpServer.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/perfetto/server/PerfettoHttpServer.kt
@@ -16,6 +16,7 @@
 
 package androidx.benchmark.macro.perfetto.server
 
+import android.annotation.SuppressLint
 import android.os.Build
 import android.security.NetworkSecurityPolicy
 import android.util.Log
@@ -60,6 +61,10 @@
         private const val READ_TIMEOUT_SECONDS = 300000
         private const val SERVER_PROCESS_NAME = "trace_processor_shell"
 
+        // Note that trace processor http server has a hard limit of 64Mb for payload size.
+        // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/src/base/http/http_server.cc;l=33
+        private const val PARSE_PAYLOAD_SIZE = 16 * 1024 * 1024 // 16Mb
+
         private var shellScript: ShellScript? = null
 
         /**
@@ -95,6 +100,7 @@
      *
      * @throws IllegalStateException if the server is not running by the end of the timeout.
      */
+    @SuppressLint("BanThreadSleep")
     fun startServer() = userspaceTrace("PerfettoHttpServer#startServer") {
         if (processId != null) {
             Log.w(TAG, "Tried to start a trace shell processor that is already running.")
@@ -212,13 +218,21 @@
      * Parses the trace file in chunks. Note that [notifyEof] should be called at the end to let
      * the processor know that no more chunks will be sent.
      */
-    fun parse(bytes: ByteArray): AppendTraceDataResult =
-        httpRequest(
-            method = METHOD_POST,
-            url = PATH_PARSE,
-            encodeBlock = { it.write(bytes) },
-            decodeBlock = { AppendTraceDataResult.ADAPTER.decode(it) }
-        )
+    fun parse(inputStream: InputStream): List<AppendTraceDataResult> {
+        val responses = mutableListOf<AppendTraceDataResult>()
+        while (true) {
+            val buffer = ByteArray(PARSE_PAYLOAD_SIZE)
+            val read = inputStream.read(buffer)
+            if (read <= 0) break
+            responses.add(httpRequest(
+                method = METHOD_POST,
+                url = PATH_PARSE,
+                encodeBlock = { it.write(buffer, 0, read) },
+                decodeBlock = { AppendTraceDataResult.ADAPTER.decode(it) }
+            ))
+        }
+        return responses
+    }
 
     /**
      * Notifies that the entire trace has been uploaded and no more chunks will be sent.
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt
index 64d2eef..9314bde 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt
@@ -21,6 +21,7 @@
 import androidx.benchmark.macro.perfetto.server.PerfettoHttpServer
 import androidx.benchmark.userspaceTrace
 import java.io.File
+import java.io.FileInputStream
 import java.io.InputStream
 import org.intellij.lang.annotations.Language
 import perfetto.protos.QueryResult
@@ -292,10 +293,8 @@
                 clearTrace()
             }
 
-            val parseResult = perfettoHttpServer.parse(traceFile.readBytes())
-            if (parseResult.error != null) {
-                throw IllegalStateException(parseResult.error)
-            }
+            val parseResults = perfettoHttpServer.parse(FileInputStream(traceFile))
+            parseResults.forEach { if (it.error != null) throw IllegalStateException(it.error) }
 
             // Notifies the server that it won't receive any more trace parts
             perfettoHttpServer.notifyEof()
diff --git a/benchmark/gradle-plugin/src/main/resources/scripts/lockClocks.sh b/benchmark/gradle-plugin/src/main/resources/scripts/lockClocks.sh
index b33734b..cc07a21 100755
--- a/benchmark/gradle-plugin/src/main/resources/scripts/lockClocks.sh
+++ b/benchmark/gradle-plugin/src/main/resources/scripts/lockClocks.sh
@@ -381,7 +381,7 @@
 
 function_lock_cpu
 
-if [ "$DEVICE" -ne "wembley" ]; then
+if [ ${DEVICE} != "wembley" ]; then
     function_lock_gpu_kgsl
 else
     echo "Unable to lock gpu clocks of $MODEL ($DEVICE)."
diff --git a/benchmark/integration-tests/baselineprofile-consumer/src/release/generated/baselineProfiles/expected-baseline-prof.txt b/benchmark/integration-tests/baselineprofile-consumer/src/release/generated/baselineProfiles/expected-baseline-prof.txt
index 59b9c7d..bac885e 100644
--- a/benchmark/integration-tests/baselineprofile-consumer/src/release/generated/baselineProfiles/expected-baseline-prof.txt
+++ b/benchmark/integration-tests/baselineprofile-consumer/src/release/generated/baselineProfiles/expected-baseline-prof.txt
@@ -1,127 +1,196 @@
-Landroidx/appcompat/view/menu/MenuPresenter$Callback;
-Landroidx/appcompat/widget/TintTypedArray;
-HSPLandroidx/appcompat/widget/TintTypedArray;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
-HSPLandroidx/appcompat/widget/TintTypedArray;->measure(Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Z)Z
-HSPLandroidx/appcompat/widget/TintTypedArray;->solveLinearSystem(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;II)V
 Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;
+HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;->$r8$lambda$CNqLK7smWTFjXaIfqGSDUWf8U50(Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;)V
+PLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;->$r8$lambda$G2Q0ZfVkJNYXyLJAm2IZ1xq3Lto(Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;)V
 HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;-><init>()V
 HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;->onCreate(Landroid/os/Bundle;)V
+PLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;->onResume$lambda$1$lambda$0(Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;)V
+HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;->onResume$lambda$1(Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;)V
 HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;->onResume()V
-Landroidx/collection/ArrayMap$1;
-HSPLandroidx/collection/ArrayMap$1;-><init>()V
+PLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity$$ExternalSyntheticLambda0;-><init>(Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;)V
+PLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity$$ExternalSyntheticLambda0;->run()V
+Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity$$ExternalSyntheticLambda1;
+HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity$$ExternalSyntheticLambda1;-><init>(Landroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity;)V
+HSPLandroidx/benchmark/integration/baselineprofile/consumer/EmptyActivity$$ExternalSyntheticLambda1;->run()V
 Landroidx/concurrent/futures/AbstractResolvableFuture;
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture;-><clinit>()V
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture;-><init>()V
+PLandroidx/concurrent/futures/AbstractResolvableFuture;->afterDone()V
+PLandroidx/concurrent/futures/AbstractResolvableFuture;->clearListeners(Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;)Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;
 PLandroidx/concurrent/futures/AbstractResolvableFuture;->complete(Landroidx/concurrent/futures/AbstractResolvableFuture;)V
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture;->get()Ljava/lang/Object;
 PLandroidx/concurrent/futures/AbstractResolvableFuture;->getDoneValue(Ljava/lang/Object;)Ljava/lang/Object;
+PLandroidx/concurrent/futures/AbstractResolvableFuture;->releaseWaiters()V
+PLandroidx/concurrent/futures/AbstractResolvableFuture;->set(Ljava/lang/Object;)Z
+Landroidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper;
+HSPLandroidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper;-><init>()V
+HSPLandroidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper;-><init>(Landroidx/concurrent/futures/AbstractResolvableFuture$1;)V
 Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;
 PLandroidx/concurrent/futures/AbstractResolvableFuture$Listener;-><clinit>()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$Listener;-><init>()V
+PLandroidx/concurrent/futures/AbstractResolvableFuture$Listener;-><init>(Ljava/lang/Runnable;Ljava/util/concurrent/Executor;)V
 Landroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;-><init>(Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;)V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casListeners(Landroidx/concurrent/futures/AbstractResolvableFuture;Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;)Z
+PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casListeners(Landroidx/concurrent/futures/AbstractResolvableFuture;Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;)Z
 PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casValue(Landroidx/concurrent/futures/AbstractResolvableFuture;Ljava/lang/Object;Ljava/lang/Object;)Z
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casWaiters(Landroidx/concurrent/futures/AbstractResolvableFuture;Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;)Z
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->putNext(Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;)V
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->putThread(Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;Ljava/lang/Thread;)V
+Landroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper$$ExternalSyntheticBackportWithForwarding0;
+HSPLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper$$ExternalSyntheticBackportWithForwarding0;->m(Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z
+Landroidx/concurrent/futures/AbstractResolvableFuture$SetFuture;
 Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;-><clinit>()V
 HSPLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;-><init>()V
-HSPLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;-><init>(I)V
+HSPLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;-><init>(Z)V
+HSPLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;->setNext(Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;)V
+PLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;->unpark()V
 Landroidx/concurrent/futures/ResolvableFuture;
 HSPLandroidx/concurrent/futures/ResolvableFuture;-><init>()V
+HSPLandroidx/concurrent/futures/ResolvableFuture;->create()Landroidx/concurrent/futures/ResolvableFuture;
+PLandroidx/concurrent/futures/ResolvableFuture;->set(Ljava/lang/Object;)Z
 Landroidx/constraintlayout/solver/ArrayLinkedVariables;
-HSPLandroidx/constraintlayout/solver/ArrayLinkedVariables;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayLinkedVariables;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/ArrayLinkedVariables;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/constraintlayout/solver/Cache;)V
 Landroidx/constraintlayout/solver/ArrayRow;
 HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>()V
-HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>(Landroidx/collection/ArrayMap$1;)V
-HSPLandroidx/constraintlayout/solver/ArrayRow;->addError(Landroidx/constraintlayout/solver/LinearSystem;I)V
-HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
-HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>(Landroidx/constraintlayout/solver/Cache;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->addError(Landroidx/constraintlayout/solver/LinearSystem;I)Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->addSingleError(Landroidx/constraintlayout/solver/SolverVariable;I)Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->chooseSubject(Landroidx/constraintlayout/solver/LinearSystem;)Z
+HSPLandroidx/constraintlayout/solver/ArrayRow;->chooseSubjectInVariables(Landroidx/constraintlayout/solver/LinearSystem;)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowCentering(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IFLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowEquals(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->ensurePositiveConstant()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->getKey()Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/ArrayRow;->hasKeyVariable()Z
+HSPLandroidx/constraintlayout/solver/ArrayRow;->isEmpty()Z
+HSPLandroidx/constraintlayout/solver/ArrayRow;->isNew(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/LinearSystem;)Z
 HSPLandroidx/constraintlayout/solver/ArrayRow;->pivot(Landroidx/constraintlayout/solver/SolverVariable;)V
 HSPLandroidx/constraintlayout/solver/ArrayRow;->reset()V
-HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromFinalVariable(Landroidx/constraintlayout/solver/SolverVariable;Z)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromFinalVariable(Landroidx/constraintlayout/solver/LinearSystem;Landroidx/constraintlayout/solver/SolverVariable;Z)V
 HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromSystem(Landroidx/constraintlayout/solver/LinearSystem;)V
 Landroidx/constraintlayout/solver/ArrayRow$ArrayRowVariables;
+Landroidx/constraintlayout/solver/Cache;
+HSPLandroidx/constraintlayout/solver/Cache;-><init>()V
 Landroidx/constraintlayout/solver/LinearSystem;
+HSPLandroidx/constraintlayout/solver/LinearSystem;-><clinit>()V
 HSPLandroidx/constraintlayout/solver/LinearSystem;-><init>()V
-HSPLandroidx/constraintlayout/solver/LinearSystem;->acquireSolverVariable$enumunboxing$(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->acquireSolverVariable(Landroidx/constraintlayout/solver/SolverVariable$Type;Ljava/lang/String;)Landroidx/constraintlayout/solver/SolverVariable;
 HSPLandroidx/constraintlayout/solver/LinearSystem;->addCentering(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IFLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
 HSPLandroidx/constraintlayout/solver/LinearSystem;->addConstraint(Landroidx/constraintlayout/solver/ArrayRow;)V
 HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;I)V
-HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)Landroidx/constraintlayout/solver/ArrayRow;
 HSPLandroidx/constraintlayout/solver/LinearSystem;->addGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
 HSPLandroidx/constraintlayout/solver/LinearSystem;->addLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
 HSPLandroidx/constraintlayout/solver/LinearSystem;->addRow(Landroidx/constraintlayout/solver/ArrayRow;)V
-HSPLandroidx/constraintlayout/solver/LinearSystem;->createErrorVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addSingleError(Landroidx/constraintlayout/solver/ArrayRow;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->computeValues()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createErrorVariable(ILjava/lang/String;)Landroidx/constraintlayout/solver/SolverVariable;
 HSPLandroidx/constraintlayout/solver/LinearSystem;->createObjectVariable(Ljava/lang/Object;)Landroidx/constraintlayout/solver/SolverVariable;
 HSPLandroidx/constraintlayout/solver/LinearSystem;->createRow()Landroidx/constraintlayout/solver/ArrayRow;
 HSPLandroidx/constraintlayout/solver/LinearSystem;->createSlackVariable()Landroidx/constraintlayout/solver/SolverVariable;
-HSPLandroidx/constraintlayout/solver/LinearSystem;->getObjectVariableValue(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;)I
+HSPLandroidx/constraintlayout/solver/LinearSystem;->enforceBFS(Landroidx/constraintlayout/solver/LinearSystem$Row;)I
+HSPLandroidx/constraintlayout/solver/LinearSystem;->getCache()Landroidx/constraintlayout/solver/Cache;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->getMetrics()Landroidx/constraintlayout/solver/Metrics;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->getObjectVariableValue(Ljava/lang/Object;)I
 HSPLandroidx/constraintlayout/solver/LinearSystem;->increaseTableSize()V
-HSPLandroidx/constraintlayout/solver/LinearSystem;->optimize(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->minimize()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->minimizeGoal(Landroidx/constraintlayout/solver/LinearSystem$Row;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->optimize(Landroidx/constraintlayout/solver/LinearSystem$Row;Z)I
 HSPLandroidx/constraintlayout/solver/LinearSystem;->releaseRows()V
 HSPLandroidx/constraintlayout/solver/LinearSystem;->reset()V
+Landroidx/constraintlayout/solver/LinearSystem$Row;
 Landroidx/constraintlayout/solver/LinearSystem$ValuesRow;
-HSPLandroidx/constraintlayout/solver/LinearSystem$ValuesRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem$ValuesRow;-><init>(Landroidx/constraintlayout/solver/LinearSystem;Landroidx/constraintlayout/solver/Cache;)V
+Landroidx/constraintlayout/solver/Pools$Pool;
 Landroidx/constraintlayout/solver/Pools$SimplePool;
-HSPLandroidx/constraintlayout/solver/Pools$SimplePool;-><init>()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;-><init>(I)V
 HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->acquire()Ljava/lang/Object;
-HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->release(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->release(Ljava/lang/Object;)Z
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->releaseAll([Ljava/lang/Object;I)V
 Landroidx/constraintlayout/solver/PriorityGoalRow;
-HSPLandroidx/constraintlayout/solver/PriorityGoalRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;-><init>(Landroidx/constraintlayout/solver/Cache;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->addError(Landroidx/constraintlayout/solver/SolverVariable;)V
 HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->addToGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
-HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->getPivotCandidate([Z)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->clear()V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->getPivotCandidate(Landroidx/constraintlayout/solver/LinearSystem;[Z)Landroidx/constraintlayout/solver/SolverVariable;
 HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->removeGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
 HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
 Landroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;
-HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;-><init>(Landroidx/constraintlayout/solver/PriorityGoalRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;-><init>(Landroidx/constraintlayout/solver/PriorityGoalRow;Landroidx/constraintlayout/solver/PriorityGoalRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;->addToGoal(Landroidx/constraintlayout/solver/SolverVariable;F)Z
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;->init(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;->isNegative()Z
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;->reset()V
 Landroidx/constraintlayout/solver/SolverVariable;
-HSPLandroidx/constraintlayout/solver/SolverVariable;-><init>(I)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/SolverVariable;-><init>(Landroidx/constraintlayout/solver/SolverVariable$Type;Ljava/lang/String;)V
 HSPLandroidx/constraintlayout/solver/SolverVariable;->addToRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->increaseErrorId()V
 HSPLandroidx/constraintlayout/solver/SolverVariable;->removeFromRow(Landroidx/constraintlayout/solver/ArrayRow;)V
 HSPLandroidx/constraintlayout/solver/SolverVariable;->reset()V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->setFinalValue(Landroidx/constraintlayout/solver/LinearSystem;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->setType(Landroidx/constraintlayout/solver/SolverVariable$Type;Ljava/lang/String;)V
 HSPLandroidx/constraintlayout/solver/SolverVariable;->updateReferencesWithNewDefinition(Landroidx/constraintlayout/solver/ArrayRow;)V
-Landroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;
-HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;-><clinit>()V
-HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;->ordinal(I)I
+Landroidx/constraintlayout/solver/SolverVariable$Type;
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type;-><init>(Ljava/lang/String;I)V
 Landroidx/constraintlayout/solver/SolverVariableValues;
-HSPLandroidx/constraintlayout/solver/SolverVariableValues;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/constraintlayout/solver/Cache;)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->add(Landroidx/constraintlayout/solver/SolverVariable;FZ)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addToHashMap(Landroidx/constraintlayout/solver/SolverVariable;I)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addVariable(ILandroidx/constraintlayout/solver/SolverVariable;F)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->clear()V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->divideByAmount(F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->findEmptySlot()I
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->get(Landroidx/constraintlayout/solver/SolverVariable;)F
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getCurrentSize()I
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariableValue(I)F
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->indexOf(Landroidx/constraintlayout/solver/SolverVariable;)I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->insertVariable(ILandroidx/constraintlayout/solver/SolverVariable;F)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->invert()V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->put(Landroidx/constraintlayout/solver/SolverVariable;F)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->remove(Landroidx/constraintlayout/solver/SolverVariable;Z)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->removeFromHashMap(Landroidx/constraintlayout/solver/SolverVariable;)V
 HSPLandroidx/constraintlayout/solver/SolverVariableValues;->use(Landroidx/constraintlayout/solver/ArrayRow;Z)F
 Landroidx/constraintlayout/solver/widgets/Barrier;
 Landroidx/constraintlayout/solver/widgets/ChainHead;
 Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->connect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->connect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;IIZ)Z
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->getMargin()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->getSolverVariable()Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->getTarget()Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->isConnected()Z
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->reset()V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->resetSolverVariable()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->resetSolverVariable(Landroidx/constraintlayout/solver/Cache;)V
 Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><clinit>()V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><init>(ILjava/lang/String;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><init>(Ljava/lang/String;I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;->values()[Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;
 Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;-><clinit>()V
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->addAnchors()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->addFirst()Z
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->addToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->applyConstraints$enumunboxing$(Landroidx/constraintlayout/solver/LinearSystem;ZZZZLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IZLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;IIIIFZZZZIIIIFZ)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->applyConstraints(Landroidx/constraintlayout/solver/LinearSystem;ZZZZLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;ZLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;IIIIFZZZZIIIIFZ)V
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->createObjectVariables(Landroidx/constraintlayout/solver/LinearSystem;)V
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getAnchor(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getDimensionBehaviour$enumunboxing$(I)I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getBaselineDistance()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getCompanionWidget()Ljava/lang/Object;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getDimensionBehaviour(I)Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getHeight()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getHorizontalDimensionBehaviour()Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getMinHeight()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getMinWidth()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getParent()Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getVerticalDimensionBehaviour()Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getVisibility()I
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getWidth()I
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getX()I
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getY()I
@@ -130,27 +199,92 @@
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInHorizontalChain()Z
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInVerticalChain()Z
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->reset()V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->resetSolverVariables(Landroidx/constraintlayout/solver/Cache;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setBaselineDistance(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setCompanionWidget(Ljava/lang/Object;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setDimensionRatio(Ljava/lang/String;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setFrame(IIII)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHasBaseline(Z)V
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHeight(I)V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalDimensionBehaviour$enumunboxing$(I)V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalBiasPercent(F)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalChainStyle(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalDimensionBehaviour(Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalMatchStyle(IIIF)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalWeight(F)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setInBarrier(IZ)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setMaxHeight(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setMaxWidth(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setMinHeight(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setMinWidth(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setParent(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalBiasPercent(F)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalChainStyle(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalDimensionBehaviour(Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalMatchStyle(IIIF)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalWeight(F)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVisibility(I)V
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setWidth(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setX(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setY(I)V
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->updateFromSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+Landroidx/constraintlayout/solver/widgets/ConstraintWidget$1;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget$1;-><clinit>()V
+Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;-><init>(Ljava/lang/String;I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;->values()[Landroidx/constraintlayout/solver/widgets/ConstraintWidget$DimensionBehaviour;
 Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;-><init>()V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->addChildrenToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->addChildrenToSolver(Landroidx/constraintlayout/solver/LinearSystem;)Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->getMeasurer()Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measurer;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->getOptimizationLevel()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->invalidateGraph()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->invalidateMeasures()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->isHeightMeasuredTooSmall()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->isWidthMeasuredTooSmall()Z
 HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->layout()V
-HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->measure(IIIIIIIII)J
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->optimizeFor(I)Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->resetChains()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->setMeasurer(Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measurer;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->setOptimizationLevel(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->setRtl(Z)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->updateChildrenFromSolver(Landroidx/constraintlayout/solver/LinearSystem;[Z)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->updateHierarchy()V
 Landroidx/constraintlayout/solver/widgets/Guideline;
 Landroidx/constraintlayout/solver/widgets/Helper;
 Landroidx/constraintlayout/solver/widgets/HelperWidget;
+Landroidx/constraintlayout/solver/widgets/Optimizer;
+HSPLandroidx/constraintlayout/solver/widgets/Optimizer;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/Optimizer;->checkMatchParent(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;Landroidx/constraintlayout/solver/LinearSystem;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/Optimizer;->enabled(II)Z
+Landroidx/constraintlayout/solver/widgets/VirtualLayout;
+Landroidx/constraintlayout/solver/widgets/WidgetContainer;
+HSPLandroidx/constraintlayout/solver/widgets/WidgetContainer;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/WidgetContainer;->add(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/WidgetContainer;->removeAllChildren()V
+HSPLandroidx/constraintlayout/solver/widgets/WidgetContainer;->resetSolverVariables(Landroidx/constraintlayout/solver/Cache;)V
+Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;->measure(Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measurer;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Z)Z
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;->measureChildren(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;->solveLinearSystem(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;Ljava/lang/String;II)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;->solverMeasure(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;IIIIIIIII)J
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure;->updateHierarchy(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
 Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;
 HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;-><init>()V
+Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measurer;
 Landroidx/constraintlayout/solver/widgets/analyzer/Dependency;
 Landroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;
 HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;->invalidateGraph()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;->invalidateMeasures()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;->setMeasurer(Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measurer;)V
 Landroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;
 HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyNode$Type;
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyNode$Type;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyNode$Type;-><init>(Ljava/lang/String;I)V
 Landroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;
 HSPLandroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
 Landroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;
@@ -160,22 +294,35 @@
 HSPLandroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
 Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;
 HSPLandroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun$RunType;
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/WidgetRun$RunType;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/WidgetRun$RunType;-><init>(Ljava/lang/String;I)V
 Landroidx/constraintlayout/widget/ConstraintHelper;
 Landroidx/constraintlayout/widget/ConstraintLayout;
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->access$000(Landroidx/constraintlayout/widget/ConstraintLayout;)Ljava/util/ArrayList;
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->addView(Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->applyConstraintsFromLayoutParams(ZLandroid/view/View;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;Landroid/util/SparseArray;)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->checkLayoutParams(Landroid/view/ViewGroup$LayoutParams;)Z
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->dispatchDraw(Landroid/graphics/Canvas;)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->generateLayoutParams(Landroid/util/AttributeSet;)Landroid/view/ViewGroup$LayoutParams;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->generateLayoutParams(Landroid/util/AttributeSet;)Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getPaddingWidth()I
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getViewWidget(Landroid/view/View;)Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->init(Landroid/util/AttributeSet;II)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->isRtl()Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->markHierarchyDirty()V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onLayout(ZIIII)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onMeasure(II)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onViewAdded(Landroid/view/View;)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->requestLayout()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->resolveMeasuredDimension(IIIIZZ)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->resolveSystem(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;III)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->setChildrenConstraints()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->setSelfDimensionBehaviour(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;IIII)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout;->updateHierarchy()Z
+Landroidx/constraintlayout/widget/ConstraintLayout$1;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$1;-><clinit>()V
 Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;
 HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->resolveLayoutDirection(I)V
@@ -183,90 +330,210 @@
 Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;
 HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;-><clinit>()V
 Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;
-HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;-><init>(Landroidx/constraintlayout/widget/ConstraintLayout;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;-><init>(Landroidx/constraintlayout/widget/ConstraintLayout;Landroidx/constraintlayout/widget/ConstraintLayout;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;->captureLayoutInfos(IIIIII)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;->didMeasures()V
 HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;->measure(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;)V
+Landroidx/constraintlayout/widget/ConstraintLayoutStates;
+Landroidx/constraintlayout/widget/ConstraintSet;
 Landroidx/constraintlayout/widget/Guideline;
+Landroidx/constraintlayout/widget/Placeholder;
 Landroidx/constraintlayout/widget/R$styleable;
 HSPLandroidx/constraintlayout/widget/R$styleable;-><clinit>()V
+Landroidx/constraintlayout/widget/VirtualLayout;
 Landroidx/core/app/CoreComponentFactory;
 HSPLandroidx/core/app/CoreComponentFactory;-><init>()V
+HSPLandroidx/core/app/CoreComponentFactory;->checkCompatWrapper(Ljava/lang/Object;)Ljava/lang/Object;
 HSPLandroidx/core/app/CoreComponentFactory;->instantiateActivity(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/app/Activity;
 HSPLandroidx/core/app/CoreComponentFactory;->instantiateApplication(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/app/Application;
 HSPLandroidx/core/app/CoreComponentFactory;->instantiateProvider(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/content/ContentProvider;
 PLandroidx/core/app/CoreComponentFactory;->instantiateReceiver(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/content/BroadcastReceiver;
-Landroidx/core/view/ViewCompat$$ExternalSyntheticApiModelOutline2;
-HSPLandroidx/core/view/ViewCompat$$ExternalSyntheticApiModelOutline2;->m()Landroid/view/Choreographer;
-HSPLandroidx/core/view/ViewCompat$$ExternalSyntheticApiModelOutline2;->m(Landroid/view/Choreographer;Landroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda2;)V
-Landroidx/core/view/ViewCompat$3$$ExternalSyntheticApiModelOutline0;
-HSPLandroidx/core/view/ViewCompat$3$$ExternalSyntheticApiModelOutline0;->m(Landroid/os/Looper;)Landroid/os/Handler;
+Landroidx/core/app/CoreComponentFactory$CompatWrapped;
+Landroidx/core/app/NavUtils$$ExternalSyntheticApiModelOutline0;
+HSPLandroidx/core/app/NavUtils$$ExternalSyntheticApiModelOutline0;->m$1(Landroidx/constraintlayout/widget/ConstraintLayout;)I
+HSPLandroidx/core/app/NavUtils$$ExternalSyntheticApiModelOutline0;->m$2(Landroidx/constraintlayout/widget/ConstraintLayout;)I
+HSPLandroidx/core/app/NavUtils$$ExternalSyntheticApiModelOutline0;->m(Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;)I
+HSPLandroidx/core/app/NavUtils$$ExternalSyntheticApiModelOutline0;->m(Landroidx/constraintlayout/widget/ConstraintLayout;)I
+Landroidx/core/os/TraceCompat$$ExternalSyntheticApiModelOutline0;
+HSPLandroidx/core/os/TraceCompat$$ExternalSyntheticApiModelOutline0;->m()Z
+Landroidx/profileinstaller/Encoding$$ExternalSyntheticApiModelOutline0;
+HSPLandroidx/profileinstaller/Encoding$$ExternalSyntheticApiModelOutline0;->m()Landroid/view/Choreographer;
+HSPLandroidx/profileinstaller/Encoding$$ExternalSyntheticApiModelOutline0;->m(Landroid/os/Looper;)Landroid/os/Handler;
+HSPLandroidx/profileinstaller/Encoding$$ExternalSyntheticApiModelOutline0;->m(Landroid/view/Choreographer;Landroid/view/Choreographer$FrameCallback;)V
 PLandroidx/profileinstaller/ProfileInstallReceiver;-><init>()V
 PLandroidx/profileinstaller/ProfileInstallReceiver;->onReceive(Landroid/content/Context;Landroid/content/Intent;)V
-PLandroidx/profileinstaller/ProfileInstaller$$ExternalSyntheticLambda1;-><init>(I)V
-Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;
+PLandroidx/profileinstaller/ProfileInstallReceiver;->saveProfile(Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;)V
+PLandroidx/profileinstaller/ProfileInstallReceiver$$ExternalSyntheticLambda0;-><init>()V
+PLandroidx/profileinstaller/ProfileInstallReceiver$ResultDiagnostics;-><init>(Landroidx/profileinstaller/ProfileInstallReceiver;)V
+PLandroidx/profileinstaller/ProfileInstallReceiver$ResultDiagnostics;->onResultReceived(ILjava/lang/Object;)V
+PLandroidx/profileinstaller/ProfileInstaller;-><clinit>()V
+PLandroidx/profileinstaller/ProfileInstaller;->hasAlreadyWrittenProfileForThisInstall(Landroid/content/pm/PackageInfo;Ljava/io/File;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;)Z
+PLandroidx/profileinstaller/ProfileInstaller;->writeProfile(Landroid/content/Context;)V
+PLandroidx/profileinstaller/ProfileInstaller;->writeProfile(Landroid/content/Context;Ljava/util/concurrent/Executor;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;)V
+PLandroidx/profileinstaller/ProfileInstaller;->writeProfile(Landroid/content/Context;Ljava/util/concurrent/Executor;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;Z)V
+PLandroidx/profileinstaller/ProfileInstaller$1;-><init>()V
+PLandroidx/profileinstaller/ProfileInstaller$1;->onResultReceived(ILjava/lang/Object;)V
+PLandroidx/profileinstaller/ProfileInstaller$2;-><init>()V
+PLandroidx/profileinstaller/ProfileInstaller$2;->onResultReceived(ILjava/lang/Object;)V
 Landroidx/profileinstaller/ProfileInstallerInitializer;
 HSPLandroidx/profileinstaller/ProfileInstallerInitializer;-><init>()V
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->create(Landroid/content/Context;)Landroidx/profileinstaller/ProfileInstallerInitializer$Result;
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->create(Landroid/content/Context;)Ljava/lang/Object;
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->delayAfterFirstFrame(Landroid/content/Context;)V
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->dependencies()Ljava/util/List;
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->installAfterDelay(Landroid/content/Context;)V
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->lambda$delayAfterFirstFrame$0$androidx-profileinstaller-ProfileInstallerInitializer(Landroid/content/Context;)V
+PLandroidx/profileinstaller/ProfileInstallerInitializer;->lambda$installAfterDelay$1(Landroid/content/Context;)V
+PLandroidx/profileinstaller/ProfileInstallerInitializer;->lambda$writeInBackground$2(Landroid/content/Context;)V
+PLandroidx/profileinstaller/ProfileInstallerInitializer;->writeInBackground(Landroid/content/Context;)V
 Landroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;-><init>(ILjava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;->run()V
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;-><init>(Landroid/content/Context;)V
+PLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;->run()V
 Landroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;-><init>(Landroid/content/Context;I)V
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;-><init>(Landroidx/profileinstaller/ProfileInstallerInitializer;Landroid/content/Context;)V
 HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;->run()V
+PLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda2;-><init>(Landroid/content/Context;)V
+PLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda2;->run()V
 Landroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;->lambda$postFrameCallback$0(Ljava/lang/Runnable;J)V
 HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;->postFrameCallback(Ljava/lang/Runnable;)V
 Landroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda2;
 HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda2;-><init>(Ljava/lang/Runnable;)V
 HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda2;->doFrame(J)V
 Landroidx/profileinstaller/ProfileInstallerInitializer$Handler28Impl;
 HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Handler28Impl;->createAsync(Landroid/os/Looper;)Landroid/os/Handler;
+Landroidx/profileinstaller/ProfileInstallerInitializer$Result;
+HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Result;-><init>()V
 Landroidx/profileinstaller/ProfileVerifier;
 HSPLandroidx/profileinstaller/ProfileVerifier;-><clinit>()V
+HSPLandroidx/profileinstaller/ProfileVerifier;->getCompilationStatusAsync()Lcom/google/common/util/concurrent/ListenableFuture;
+PLandroidx/profileinstaller/ProfileVerifier;->getPackageLastUpdateTime(Landroid/content/Context;)J
 PLandroidx/profileinstaller/ProfileVerifier;->setCompilationStatus(IZZ)Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;
-PLandroidx/profileinstaller/ProfileVerifier;->writeProfileVerification(Landroid/content/Context;Z)V
+PLandroidx/profileinstaller/ProfileVerifier;->writeProfileVerification(Landroid/content/Context;Z)Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;
 PLandroidx/profileinstaller/ProfileVerifier$Api33Impl;->getPackageInfo(Landroid/content/pm/PackageManager;Landroid/content/Context;)Landroid/content/pm/PackageInfo;
-PLandroidx/profileinstaller/ProfileVerifier$Api33Impl$$ExternalSyntheticApiModelOutline0;->m()Landroid/content/pm/PackageManager$PackageInfoFlags;
-PLandroidx/profileinstaller/ProfileVerifier$Api33Impl$$ExternalSyntheticApiModelOutline0;->m(Landroid/content/pm/PackageManager;Ljava/lang/String;Landroid/content/pm/PackageManager$PackageInfoFlags;)Landroid/content/pm/PackageInfo;
 PLandroidx/profileinstaller/ProfileVerifier$Cache;-><init>(IIJJ)V
 PLandroidx/profileinstaller/ProfileVerifier$Cache;->equals(Ljava/lang/Object;)Z
 PLandroidx/profileinstaller/ProfileVerifier$Cache;->readFromFile(Ljava/io/File;)Landroidx/profileinstaller/ProfileVerifier$Cache;
+Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;
 PLandroidx/profileinstaller/ProfileVerifier$CompilationStatus;-><init>(IZZ)V
+PLandroidx/profileinstaller/ProfileVerifier$CompilationStatus;->getProfileInstallResultCode()I
+PLandroidx/profileinstaller/ProfileVerifier$CompilationStatus;->hasProfileEnqueuedForCompilation()Z
+PLandroidx/profileinstaller/ProfileVerifier$CompilationStatus;->isCompiledWithProfile()Z
 Landroidx/startup/AppInitializer;
 HSPLandroidx/startup/AppInitializer;-><clinit>()V
 HSPLandroidx/startup/AppInitializer;-><init>(Landroid/content/Context;)V
+HSPLandroidx/startup/AppInitializer;->discoverAndInitialize()V
 HSPLandroidx/startup/AppInitializer;->discoverAndInitialize(Landroid/os/Bundle;)V
-HSPLandroidx/startup/AppInitializer;->doInitialize(Ljava/lang/Class;Ljava/util/HashSet;)V
+HSPLandroidx/startup/AppInitializer;->doInitialize(Ljava/lang/Class;Ljava/util/Set;)Ljava/lang/Object;
+HSPLandroidx/startup/AppInitializer;->getInstance(Landroid/content/Context;)Landroidx/startup/AppInitializer;
 Landroidx/startup/InitializationProvider;
 HSPLandroidx/startup/InitializationProvider;-><init>()V
 HSPLandroidx/startup/InitializationProvider;->onCreate()Z
+Landroidx/startup/Initializer;
+Landroidx/startup/R$string;
 Landroidx/tracing/Trace;
+HSPLandroidx/tracing/Trace;->beginSection(Ljava/lang/String;)V
+HSPLandroidx/tracing/Trace;->endSection()V
 HSPLandroidx/tracing/Trace;->isEnabled()Z
-Landroidx/tracing/Trace$$ExternalSyntheticApiModelOutline0;
-HSPLandroidx/tracing/Trace$$ExternalSyntheticApiModelOutline0;->m()Z
-Landroidx/tracing/TraceApi18Impl$$ExternalSyntheticApiModelOutline0;
-HSPLandroidx/tracing/TraceApi18Impl$$ExternalSyntheticApiModelOutline0;->m()V
-HSPLandroidx/tracing/TraceApi18Impl$$ExternalSyntheticApiModelOutline0;->m(Ljava/lang/String;)V
+Landroidx/tracing/TraceApi18Impl;
+HSPLandroidx/tracing/TraceApi18Impl;->beginSection(Ljava/lang/String;)V
+HSPLandroidx/tracing/TraceApi18Impl;->endSection()V
+Lcom/google/common/util/concurrent/ListenableFuture;
 PLkotlin/Pair;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
-Lkotlin/TuplesKt;
-HSPLkotlin/TuplesKt;-><clinit>()V
-HSPLkotlin/TuplesKt;-><init>(Ljava/lang/Object;)V
-PLkotlin/TuplesKt;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V
-HSPLkotlin/TuplesKt;->checkNotNullParameter(Ljava/lang/Object;Ljava/lang/String;)V
-PLkotlin/TuplesKt;->writeProfile(Landroid/content/Context;Landroidx/profileinstaller/ProfileInstaller$$ExternalSyntheticLambda1;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;Z)V
-PLkotlin/jvm/internal/Lambda;-><init>()V
+PLkotlin/Pair;->component1()Ljava/lang/Object;
+PLkotlin/Pair;->component2()Ljava/lang/Object;
+PLkotlin/Pair;->getFirst()Ljava/lang/Object;
+PLkotlin/Pair;->getSecond()Ljava/lang/Object;
+PLkotlin/TuplesKt;->to(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
+PLkotlin/collections/ArraysKt___ArraysJvmKt;->asList([Ljava/lang/Object;)Ljava/util/List;
+PLkotlin/collections/ArraysUtilJVM;->asList([Ljava/lang/Object;)Ljava/util/List;
+PLkotlin/collections/CollectionsKt__CollectionsKt;->getLastIndex(Ljava/util/List;)I
+PLkotlin/collections/CollectionsKt__CollectionsKt;->optimizeReadOnlyList(Ljava/util/List;)Ljava/util/List;
+PLkotlin/collections/CollectionsKt__IterablesKt;->collectionSizeOrDefault(Ljava/lang/Iterable;I)I
+PLkotlin/collections/CollectionsKt___CollectionsKt;->joinTo$default(Ljava/lang/Iterable;Ljava/lang/Appendable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Appendable;
+PLkotlin/collections/CollectionsKt___CollectionsKt;->joinTo(Ljava/lang/Iterable;Ljava/lang/Appendable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;)Ljava/lang/Appendable;
+PLkotlin/collections/CollectionsKt___CollectionsKt;->minOrNull(Ljava/lang/Iterable;)Ljava/lang/Comparable;
+PLkotlin/collections/IntIterator;-><init>()V
+PLkotlin/internal/ProgressionUtilKt;->differenceModulo(III)I
+PLkotlin/internal/ProgressionUtilKt;->getProgressionLastElement(III)I
+PLkotlin/internal/ProgressionUtilKt;->mod(II)I
+Lkotlin/jvm/internal/Intrinsics;
+PLkotlin/jvm/internal/Intrinsics;->checkNotNull(Ljava/lang/Object;Ljava/lang/String;)V
+PLkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V
+HSPLkotlin/jvm/internal/Intrinsics;->checkNotNullParameter(Ljava/lang/Object;Ljava/lang/String;)V
+PLkotlin/jvm/internal/Lambda;-><init>(I)V
+PLkotlin/ranges/IntProgression;-><clinit>()V
 PLkotlin/ranges/IntProgression;-><init>(III)V
+PLkotlin/ranges/IntProgression;->getFirst()I
+PLkotlin/ranges/IntProgression;->getLast()I
+PLkotlin/ranges/IntProgression;->getStep()I
 PLkotlin/ranges/IntProgression;->iterator()Ljava/util/Iterator;
+PLkotlin/ranges/IntProgression;->iterator()Lkotlin/collections/IntIterator;
+PLkotlin/ranges/IntProgression$Companion;-><init>()V
+PLkotlin/ranges/IntProgression$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
 PLkotlin/ranges/IntProgressionIterator;-><init>(III)V
+PLkotlin/ranges/IntProgressionIterator;->hasNext()Z
+PLkotlin/ranges/IntProgressionIterator;->nextInt()I
 PLkotlin/ranges/IntRange;-><clinit>()V
 PLkotlin/ranges/IntRange;-><init>(II)V
-Lkotlin/ranges/IntRange$Companion;
-HSPLkotlin/ranges/IntRange$Companion;-><init>(I)V
-PLkotlin/ranges/IntRange$Companion;->onResultReceived(ILjava/lang/Object;)V
-PLkotlin/text/DelimitedRangesSequence;-><init>(Ljava/lang/String;IILkotlin/text/StringsKt__StringsKt$rangesDelimitedBy$2;)V
+PLkotlin/ranges/IntRange;->getEndInclusive()Ljava/lang/Integer;
+PLkotlin/ranges/IntRange;->getStart()Ljava/lang/Integer;
+PLkotlin/ranges/IntRange$Companion;-><init>()V
+PLkotlin/ranges/IntRange$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+PLkotlin/ranges/RangesKt___RangesKt;->coerceAtLeast(II)I
+PLkotlin/ranges/RangesKt___RangesKt;->coerceAtMost(II)I
+PLkotlin/ranges/RangesKt___RangesKt;->coerceIn(III)I
+PLkotlin/ranges/RangesKt___RangesKt;->until(II)Lkotlin/ranges/IntRange;
+PLkotlin/sequences/SequencesKt___SequencesKt;->map(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
+PLkotlin/sequences/SequencesKt___SequencesKt;->toCollection(Lkotlin/sequences/Sequence;Ljava/util/Collection;)Ljava/util/Collection;
+PLkotlin/sequences/SequencesKt___SequencesKt;->toList(Lkotlin/sequences/Sequence;)Ljava/util/List;
+PLkotlin/sequences/SequencesKt___SequencesKt;->toMutableList(Lkotlin/sequences/Sequence;)Ljava/util/List;
+PLkotlin/sequences/TransformingSequence;-><init>(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)V
+PLkotlin/sequences/TransformingSequence;->access$getSequence$p(Lkotlin/sequences/TransformingSequence;)Lkotlin/sequences/Sequence;
+PLkotlin/sequences/TransformingSequence;->access$getTransformer$p(Lkotlin/sequences/TransformingSequence;)Lkotlin/jvm/functions/Function1;
+PLkotlin/sequences/TransformingSequence;->iterator()Ljava/util/Iterator;
+PLkotlin/sequences/TransformingSequence$iterator$1;-><init>(Lkotlin/sequences/TransformingSequence;)V
+PLkotlin/sequences/TransformingSequence$iterator$1;->hasNext()Z
+PLkotlin/sequences/TransformingSequence$iterator$1;->next()Ljava/lang/Object;
+PLkotlin/text/CharsKt__CharJVMKt;->isWhitespace(C)Z
+PLkotlin/text/DelimitedRangesSequence;-><init>(Ljava/lang/CharSequence;IILkotlin/jvm/functions/Function2;)V
+PLkotlin/text/DelimitedRangesSequence;->access$getGetNextMatch$p(Lkotlin/text/DelimitedRangesSequence;)Lkotlin/jvm/functions/Function2;
+PLkotlin/text/DelimitedRangesSequence;->access$getInput$p(Lkotlin/text/DelimitedRangesSequence;)Ljava/lang/CharSequence;
+PLkotlin/text/DelimitedRangesSequence;->access$getLimit$p(Lkotlin/text/DelimitedRangesSequence;)I
+PLkotlin/text/DelimitedRangesSequence;->access$getStartIndex$p(Lkotlin/text/DelimitedRangesSequence;)I
 PLkotlin/text/DelimitedRangesSequence;->iterator()Ljava/util/Iterator;
 PLkotlin/text/DelimitedRangesSequence$iterator$1;-><init>(Lkotlin/text/DelimitedRangesSequence;)V
 PLkotlin/text/DelimitedRangesSequence$iterator$1;->calcNext()V
 PLkotlin/text/DelimitedRangesSequence$iterator$1;->hasNext()Z
 PLkotlin/text/DelimitedRangesSequence$iterator$1;->next()Ljava/lang/Object;
-PLkotlin/text/StringsKt__StringsKt;->isBlank(Ljava/lang/String;)Z
+PLkotlin/text/DelimitedRangesSequence$iterator$1;->next()Lkotlin/ranges/IntRange;
+PLkotlin/text/StringsKt__AppendableKt;->appendElement(Ljava/lang/Appendable;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+PLkotlin/text/StringsKt__IndentKt;->getIndentFunction$StringsKt__IndentKt(Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+PLkotlin/text/StringsKt__IndentKt;->indentWidth$StringsKt__IndentKt(Ljava/lang/String;)I
+PLkotlin/text/StringsKt__IndentKt;->replaceIndent(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+PLkotlin/text/StringsKt__IndentKt;->trimIndent(Ljava/lang/String;)Ljava/lang/String;
+PLkotlin/text/StringsKt__IndentKt$getIndentFunction$1;-><clinit>()V
+PLkotlin/text/StringsKt__IndentKt$getIndentFunction$1;-><init>()V
+PLkotlin/text/StringsKt__IndentKt$getIndentFunction$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+PLkotlin/text/StringsKt__IndentKt$getIndentFunction$1;->invoke(Ljava/lang/String;)Ljava/lang/String;
+PLkotlin/text/StringsKt__StringsJVMKt;->isBlank(Ljava/lang/CharSequence;)Z
+PLkotlin/text/StringsKt__StringsJVMKt;->regionMatches(Ljava/lang/String;ILjava/lang/String;IIZ)Z
+PLkotlin/text/StringsKt__StringsKt;->access$findAnyOf(Ljava/lang/CharSequence;Ljava/util/Collection;IZZ)Lkotlin/Pair;
+PLkotlin/text/StringsKt__StringsKt;->findAnyOf$StringsKt__StringsKt(Ljava/lang/CharSequence;Ljava/util/Collection;IZZ)Lkotlin/Pair;
+PLkotlin/text/StringsKt__StringsKt;->getIndices(Ljava/lang/CharSequence;)Lkotlin/ranges/IntRange;
+PLkotlin/text/StringsKt__StringsKt;->getLastIndex(Ljava/lang/CharSequence;)I
+PLkotlin/text/StringsKt__StringsKt;->lineSequence(Ljava/lang/CharSequence;)Lkotlin/sequences/Sequence;
+PLkotlin/text/StringsKt__StringsKt;->lines(Ljava/lang/CharSequence;)Ljava/util/List;
+PLkotlin/text/StringsKt__StringsKt;->rangesDelimitedBy$StringsKt__StringsKt$default(Ljava/lang/CharSequence;[Ljava/lang/String;IZIILjava/lang/Object;)Lkotlin/sequences/Sequence;
+PLkotlin/text/StringsKt__StringsKt;->rangesDelimitedBy$StringsKt__StringsKt(Ljava/lang/CharSequence;[Ljava/lang/String;IZI)Lkotlin/sequences/Sequence;
+PLkotlin/text/StringsKt__StringsKt;->requireNonNegativeLimit(I)V
+PLkotlin/text/StringsKt__StringsKt;->splitToSequence$default(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Lkotlin/sequences/Sequence;
+PLkotlin/text/StringsKt__StringsKt;->splitToSequence(Ljava/lang/CharSequence;[Ljava/lang/String;ZI)Lkotlin/sequences/Sequence;
+PLkotlin/text/StringsKt__StringsKt;->substring(Ljava/lang/CharSequence;Lkotlin/ranges/IntRange;)Ljava/lang/String;
 PLkotlin/text/StringsKt__StringsKt$rangesDelimitedBy$2;-><init>(Ljava/util/List;Z)V
-PLkotlin/text/StringsKt__StringsKt$splitToSequence$1;-><init>(ILjava/lang/String;)V
-PLkotlin/text/StringsKt__StringsKt$splitToSequence$1;->invoke(Ljava/lang/Object;)Ljava/lang/String;
\ No newline at end of file
+PLkotlin/text/StringsKt__StringsKt$rangesDelimitedBy$2;->invoke(Ljava/lang/CharSequence;I)Lkotlin/Pair;
+PLkotlin/text/StringsKt__StringsKt$rangesDelimitedBy$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+PLkotlin/text/StringsKt__StringsKt$splitToSequence$1;-><init>(Ljava/lang/CharSequence;)V
+PLkotlin/text/StringsKt__StringsKt$splitToSequence$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+PLkotlin/text/StringsKt__StringsKt$splitToSequence$1;->invoke(Lkotlin/ranges/IntRange;)Ljava/lang/String;
+PLkotlin/text/StringsKt___StringsKt;->drop(Ljava/lang/String;I)Ljava/lang/String;
\ No newline at end of file
diff --git a/biometric/biometric/src/main/res/values-am/strings.xml b/biometric/biometric/src/main/res/values-am/strings.xml
index a32005d..28d2673 100644
--- a/biometric/biometric/src/main/res/values-am/strings.xml
+++ b/biometric/biometric/src/main/res/values-am/strings.xml
@@ -33,15 +33,15 @@
     <string name="use_fingerprint_label" msgid="6961788485681412417">"የጣት አሻራን ተጠቀም"</string>
     <string name="use_face_label" msgid="6533512708069459542">"መልክን ተጠቀም"</string>
     <string name="use_biometric_label" msgid="6524145989441579428">"ባዮሜትሪኮችን ተጠቀም"</string>
-    <string name="use_screen_lock_label" msgid="5459869335976243512">"የማያ ገጽ መቆለፊያን ተጠቀም"</string>
-    <string name="use_fingerprint_or_screen_lock_label" msgid="7577690399303139443">"የጣት አሻራን ወይም የማያ ገጽ መቆለፊያን ይጠቀሙ"</string>
-    <string name="use_face_or_screen_lock_label" msgid="2116180187159450292">"የመልክ ወይም የማያ ገጽ መቆለፊያን ተጠቀም"</string>
-    <string name="use_biometric_or_screen_lock_label" msgid="5385448280139639016">"ባዮሜትሪኮችን ወይም ማያ ገጽ መቆለፊያን ይጠቀሙ"</string>
+    <string name="use_screen_lock_label" msgid="5459869335976243512">"የማያ ገፅ መቆለፊያን ተጠቀም"</string>
+    <string name="use_fingerprint_or_screen_lock_label" msgid="7577690399303139443">"የጣት አሻራን ወይም የማያ ገፅ መቆለፊያን ይጠቀሙ"</string>
+    <string name="use_face_or_screen_lock_label" msgid="2116180187159450292">"የመልክ ወይም የማያ ገፅ መቆለፊያን ተጠቀም"</string>
+    <string name="use_biometric_or_screen_lock_label" msgid="5385448280139639016">"ባዮሜትሪኮችን ወይም ማያ ገፅ መቆለፊያን ይጠቀሙ"</string>
     <string name="fingerprint_prompt_message" msgid="7449360011861769080">"ለመቀጠል የእርስዎን የጣት አሻራ ይጠቀሙ"</string>
     <string name="face_prompt_message" msgid="2282389249605674226">"ለመቀጠል የእርስዎን መልክ ይጠቀሙ"</string>
     <string name="biometric_prompt_message" msgid="1160635338192065472">"ለመቀጠል የእርስዎን ባዮሜትሪክ ይጠቀሙ"</string>
-    <string name="screen_lock_prompt_message" msgid="5659570757430909869">"ለመቀጠል የእርስዎን የማያ ገጽ ቁልፍ ያስገቡ"</string>
-    <string name="fingerprint_or_screen_lock_prompt_message" msgid="8382576858490514495">"ለመቀጠል የእርስዎን የጣት አሻራ ወይም የማያ ገጽ መቆለፊያ ይጠቀሙ"</string>
-    <string name="face_or_screen_lock_prompt_message" msgid="4562557128765735254">"ለመቀጠል የእርስዎን መልክ ወይም የማያ ገጽ መቆለፊያ ይጠቀሙ"</string>
-    <string name="biometric_or_screen_lock_prompt_message" msgid="2102429900219199821">"ለመቀጠል የእርስዎን የባዮሜትሪክ ወይም የማያ ገጽ መቆለፊያ ይጠቀሙ"</string>
+    <string name="screen_lock_prompt_message" msgid="5659570757430909869">"ለመቀጠል የእርስዎን የማያ ገፅ ቁልፍ ያስገቡ"</string>
+    <string name="fingerprint_or_screen_lock_prompt_message" msgid="8382576858490514495">"ለመቀጠል የእርስዎን የጣት አሻራ ወይም የማያ ገፅ መቆለፊያ ይጠቀሙ"</string>
+    <string name="face_or_screen_lock_prompt_message" msgid="4562557128765735254">"ለመቀጠል የእርስዎን መልክ ወይም የማያ ገፅ መቆለፊያ ይጠቀሙ"</string>
+    <string name="biometric_or_screen_lock_prompt_message" msgid="2102429900219199821">"ለመቀጠል የእርስዎን የባዮሜትሪክ ወይም የማያ ገፅ መቆለፊያ ይጠቀሙ"</string>
 </resources>
diff --git a/biometric/biometric/src/main/res/values-ky/strings.xml b/biometric/biometric/src/main/res/values-ky/strings.xml
index 4c50879..97be746 100644
--- a/biometric/biometric/src/main/res/values-ky/strings.xml
+++ b/biometric/biometric/src/main/res/values-ky/strings.xml
@@ -32,7 +32,7 @@
     <string name="fingerprint_dialog_icon_description" msgid="5462024216548165325">"Манжа изинин сүрөтчөсү"</string>
     <string name="use_fingerprint_label" msgid="6961788485681412417">"Манжа изин колдонуу"</string>
     <string name="use_face_label" msgid="6533512708069459542">"Жүзүнөн таанып ачууну колдонуу"</string>
-    <string name="use_biometric_label" msgid="6524145989441579428">"Биометрикалык жөндөөлөрдү колдонуу"</string>
+    <string name="use_biometric_label" msgid="6524145989441579428">"Биометрикалык параметрлерди колдонуу"</string>
     <string name="use_screen_lock_label" msgid="5459869335976243512">"Экран кулпусун колдонуу"</string>
     <string name="use_fingerprint_or_screen_lock_label" msgid="7577690399303139443">"Манжа изин же экрандын кулпусун колдонуу"</string>
     <string name="use_face_or_screen_lock_label" msgid="2116180187159450292">"Жүзүнөн таанып ачууну же экрандын кулпусун колдонуу"</string>
diff --git a/biometric/biometric/src/main/res/values-zh-rHK/strings.xml b/biometric/biometric/src/main/res/values-zh-rHK/strings.xml
index c732b33..1be8ed3 100644
--- a/biometric/biometric/src/main/res/values-zh-rHK/strings.xml
+++ b/biometric/biometric/src/main/res/values-zh-rHK/strings.xml
@@ -38,7 +38,7 @@
     <string name="use_face_or_screen_lock_label" msgid="2116180187159450292">"使用面孔或螢幕鎖定"</string>
     <string name="use_biometric_or_screen_lock_label" msgid="5385448280139639016">"使用生物識別或螢幕鎖定"</string>
     <string name="fingerprint_prompt_message" msgid="7449360011861769080">"請使用指紋驗證身分,才能繼續操作"</string>
-    <string name="face_prompt_message" msgid="2282389249605674226">"請使用您的面孔驗證身分,才能繼續操作"</string>
+    <string name="face_prompt_message" msgid="2282389249605674226">"請使用你的面孔驗證身分,才能繼續操作"</string>
     <string name="biometric_prompt_message" msgid="1160635338192065472">"請使用使用生物識別驗證身分,才能繼續操作"</string>
     <string name="screen_lock_prompt_message" msgid="5659570757430909869">"請輸入螢幕鎖定解鎖憑證,才能繼續操作"</string>
     <string name="fingerprint_or_screen_lock_prompt_message" msgid="8382576858490514495">"請使用指紋解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
diff --git a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/BluetoothGattCharacteristicTest.kt b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/BluetoothGattCharacteristicTest.kt
new file mode 100644
index 0000000..fe2a87b
--- /dev/null
+++ b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/BluetoothGattCharacteristicTest.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.bluetooth
+
+import android.bluetooth.BluetoothGattCharacteristic.PERMISSION_READ
+import android.bluetooth.BluetoothGattCharacteristic.PROPERTY_NOTIFY
+import android.bluetooth.BluetoothGattCharacteristic.PROPERTY_READ
+import java.util.UUID
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class BluetoothGattCharacteristicTest {
+    @Test
+    fun constructorWithFwkInstance() {
+        val characteristicUuid = UUID.randomUUID()
+        val properties = PROPERTY_READ or PROPERTY_NOTIFY
+        val permissions = PERMISSION_READ
+
+        val fwkGattCharacteristic = android.bluetooth.BluetoothGattCharacteristic(
+            characteristicUuid,
+            properties,
+            permissions,
+        )
+        val gattCharacteristic = BluetoothGattCharacteristic(fwkGattCharacteristic)
+
+        Assert.assertEquals(fwkGattCharacteristic.uuid, gattCharacteristic.uuid)
+        Assert.assertEquals(fwkGattCharacteristic.properties, gattCharacteristic.properties)
+        Assert.assertEquals(fwkGattCharacteristic.permissions, gattCharacteristic.permissions)
+    }
+}
\ No newline at end of file
diff --git a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/BluetoothGattServiceTest.kt b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/BluetoothGattServiceTest.kt
new file mode 100644
index 0000000..0ac236b
--- /dev/null
+++ b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/BluetoothGattServiceTest.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.bluetooth
+
+import android.bluetooth.BluetoothGattService as FwkBluetoothGattService
+import android.bluetooth.BluetoothGattCharacteristic as FwkBluetoothGattCharacteristic
+import android.bluetooth.BluetoothGattService.SERVICE_TYPE_PRIMARY
+import java.util.UUID
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class BluetoothGattServiceTest {
+
+    @Test
+    fun constructorWithFwkInstance() {
+        val serviceUuid = UUID.randomUUID()
+        val fwkBluetoothGattService = FwkBluetoothGattService(serviceUuid, SERVICE_TYPE_PRIMARY)
+
+        val charUuid1 = UUID.randomUUID()
+        val fwkCharacteristic1 = FwkBluetoothGattCharacteristic(charUuid1, 0, 0)
+        fwkBluetoothGattService.addCharacteristic(fwkCharacteristic1)
+
+        val charUuid2 = UUID.randomUUID()
+        val fwkCharacteristic2 = FwkBluetoothGattCharacteristic(charUuid2, 0, 0)
+        fwkBluetoothGattService.addCharacteristic(fwkCharacteristic2)
+
+        val gattService = BluetoothGattService(fwkBluetoothGattService)
+
+        assertEquals(fwkBluetoothGattService.uuid, gattService.uuid)
+        assertEquals(2, gattService.characteristics.size)
+        assertEquals(charUuid1, gattService.characteristics[0].uuid)
+        assertEquals(charUuid2, gattService.characteristics[1].uuid)
+    }
+}
\ No newline at end of file
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothGattCharacteristic.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothGattCharacteristic.kt
new file mode 100644
index 0000000..cd842d8
--- /dev/null
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothGattCharacteristic.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.bluetooth
+
+import android.bluetooth.BluetoothGattCharacteristic as FwkBluetoothGattCharacteristic
+import androidx.annotation.RestrictTo
+import java.util.UUID
+
+/**
+ * Represents a Bluetooth characteristic.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+class BluetoothGattCharacteristic internal constructor(
+    internal var characteristic: FwkBluetoothGattCharacteristic
+) {
+    val uuid: UUID
+        get() = characteristic.uuid
+    val properties: Int
+        get() = characteristic.properties
+    val permissions: Int
+        get() = characteristic.permissions
+}
\ No newline at end of file
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothGattService.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothGattService.kt
new file mode 100644
index 0000000..f5bfcbb
--- /dev/null
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothGattService.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.bluetooth
+
+import android.bluetooth.BluetoothGattService as FwkBluetoothGattService
+import androidx.annotation.RestrictTo
+import java.util.UUID
+
+/**
+ * Represents a Bluetooth GATT service.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+class BluetoothGattService internal constructor(internal var fwkService: FwkBluetoothGattService) {
+    val uuid: UUID
+        get() = fwkService.uuid
+    val characteristics: List<BluetoothGattCharacteristic> =
+        fwkService.characteristics.map { BluetoothGattCharacteristic(it) }
+}
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/BluetoothLe.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/BluetoothLe.kt
index d51a375..219af7b 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/BluetoothLe.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/BluetoothLe.kt
@@ -110,13 +110,14 @@
         fun getServices(): List<BluetoothGattService>
         fun getService(uuid: UUID): BluetoothGattService?
 
-        suspend fun read(characteristic: BluetoothGattCharacteristic): Result<ByteArray>
-        suspend fun write(
+        suspend fun readCharacteristic(characteristic: BluetoothGattCharacteristic):
+            Result<ByteArray>
+        suspend fun writeCharacteristic(
             characteristic: BluetoothGattCharacteristic,
             value: ByteArray,
             writeType: Int
         ): Result<Unit>
-        fun subscribeCharacteristic(characteristic: BluetoothGattCharacteristic): Flow<ByteArray>
+        fun subscribeToCharacteristic(characteristic: BluetoothGattCharacteristic): Flow<ByteArray>
         suspend fun awaitClose(onClosed: () -> Unit)
     }
 
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt
index 315fe6d..b305e73 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt
@@ -22,16 +22,23 @@
 import android.bluetooth.BluetoothGatt.GATT_SUCCESS
 import android.bluetooth.BluetoothGattCallback
 import android.bluetooth.BluetoothGattCharacteristic
+import android.bluetooth.BluetoothGattDescriptor
 import android.bluetooth.BluetoothGattService
 import android.content.Context
 import android.util.Log
+import androidx.collection.arrayMapOf
 import java.util.UUID
+import kotlin.coroutines.cancellation.CancellationException
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
 import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.channels.consumeEach
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.job
 import kotlinx.coroutines.launch
 
@@ -39,7 +46,9 @@
     companion object {
         private const val TAG = "GattClientImpl"
         private const val GATT_MAX_MTU = 517
+        private val CCCD_UID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
     }
+
     private data class ClientTask(
         val taskBlock: () -> Unit
     ) {
@@ -48,18 +57,25 @@
     }
 
     private sealed interface ClientCallback {
-        val characteristic: BluetoothGattCharacteristic
-
-        class OnRead(
-            override val characteristic: BluetoothGattCharacteristic,
+        class OnCharacteristicRead(
+            val characteristic: BluetoothGattCharacteristic,
             val value: ByteArray,
             val status: Int
         ) : ClientCallback
 
-        class OnWrite(
-            override val characteristic: BluetoothGattCharacteristic,
+        class OnCharacteristicWrite(
+            val characteristic: BluetoothGattCharacteristic,
             val status: Int
         ) : ClientCallback
+
+        class OnDescriptorWrite(
+            val descriptor: BluetoothGattDescriptor,
+            val status: Int
+        ) : ClientCallback
+    }
+
+    private interface SubscribeListener {
+        fun onCharacteristicNotification(value: ByteArray)
     }
 
     @SuppressLint("MissingPermission")
@@ -71,6 +87,7 @@
         val connectResult = CompletableDeferred<Boolean>(parent = coroutineContext.job)
         val finished = Job(parent = coroutineContext.job)
         var currentTask: ClientTask? = null
+        val subscribeMap: MutableMap<BluetoothGattCharacteristic, SubscribeListener> = arrayMapOf()
 
         val callback = object : BluetoothGattCallback() {
             override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
@@ -104,7 +121,7 @@
                 status: Int
             ) {
                 currentTask?.callbackChannel?.trySend(
-                    ClientCallback.OnRead(characteristic, value, status))
+                    ClientCallback.OnCharacteristicRead(characteristic, value, status))
             }
 
             override fun onCharacteristicWrite(
@@ -113,14 +130,33 @@
                 status: Int
             ) {
                 currentTask?.callbackChannel?.trySend(
-                    ClientCallback.OnWrite(characteristic, status))
+                    ClientCallback.OnCharacteristicWrite(characteristic, status))
+            }
+
+            override fun onDescriptorWrite(
+                gatt: BluetoothGatt,
+                descriptor: BluetoothGattDescriptor,
+                status: Int
+            ) {
+                currentTask?.callbackChannel?.trySend(
+                    ClientCallback.OnDescriptorWrite(descriptor, status))
+            }
+
+            override fun onCharacteristicChanged(
+                gatt: BluetoothGatt,
+                characteristic: BluetoothGattCharacteristic,
+                value: ByteArray
+            ) {
+                synchronized(subscribeMap) {
+                    subscribeMap[characteristic]?.onCharacteristicNotification(value)
+                }
             }
         }
         val bluetoothGatt = device.connectGatt(context, /*autoConnect=*/false, callback)
         val tasks: Channel<ClientTask> = Channel(10)
 
         if (!connectResult.await()) {
-            Log.d(TAG, "Failed to connect to the remote GATT server")
+            Log.w(TAG, "Failed to connect to the remote GATT server")
             return@coroutineScope
         }
         val gattScope = object : BluetoothLe.GattClientScope {
@@ -147,7 +183,7 @@
                 return bluetoothGatt.getService(uuid)
             }
 
-            override suspend fun read(characteristic: BluetoothGattCharacteristic):
+            override suspend fun readCharacteristic(characteristic: BluetoothGattCharacteristic):
                 Result<ByteArray> {
                 val task = ClientTask {
                     bluetoothGatt.readCharacteristic(characteristic)
@@ -155,7 +191,7 @@
                 tasks.send(task)
                 while (true) {
                     val res = task.callbackChannel.receive()
-                    if (res !is ClientCallback.OnRead) continue
+                    if (res !is ClientCallback.OnCharacteristicRead) continue
                     if (res.characteristic != characteristic) continue
 
                     task.finished.complete(res.status == GATT_SUCCESS)
@@ -164,8 +200,7 @@
                 }
             }
 
-            @Suppress("ClassVerificationFailure")
-            override suspend fun write(
+            override suspend fun writeCharacteristic(
                 characteristic: BluetoothGattCharacteristic,
                 value: ByteArray,
                 writeType: Int
@@ -176,7 +211,7 @@
                 tasks.send(task)
                 while (true) {
                     val res = task.callbackChannel.receive()
-                    if (res !is ClientCallback.OnWrite) continue
+                    if (res !is ClientCallback.OnCharacteristicWrite) continue
                     if (res.characteristic.uuid != characteristic.uuid) continue
 
                     task.finished.complete(res.status == GATT_SUCCESS)
@@ -185,9 +220,50 @@
                 }
             }
 
-            override fun subscribeCharacteristic(characteristic: BluetoothGattCharacteristic):
+            override fun subscribeToCharacteristic(characteristic: BluetoothGattCharacteristic):
                 Flow<ByteArray> {
-                TODO("Not yet implemented")
+                val cccd = characteristic.getDescriptor(CCCD_UID) ?: return emptyFlow()
+
+                return callbackFlow {
+                    val listener = object : SubscribeListener {
+                        override fun onCharacteristicNotification(value: ByteArray) {
+                            trySend(value)
+                        }
+                    }
+                    if (!registerSubscribeListener(characteristic, listener)) {
+                        cancel(CancellationException("already subscribed"))
+                    }
+
+                    val task = ClientTask {
+                        bluetoothGatt.setCharacteristicNotification(characteristic, /*enable=*/true)
+                        bluetoothGatt.writeDescriptor(
+                            cccd,
+                            BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+                        )
+                    }
+                    tasks.send(task)
+                    while (true) {
+                        val res = task.callbackChannel.receive()
+                        if (res !is ClientCallback.OnDescriptorWrite) continue
+                        if (res.descriptor != cccd) continue
+
+                        task.finished.complete(res.status == GATT_SUCCESS)
+                        if (res.status != GATT_SUCCESS) {
+                            cancel(CancellationException("failed to set notification"))
+                        }
+                        break
+                    }
+
+                    this.awaitClose {
+                        unregisterSubscribeListener(characteristic)
+                        bluetoothGatt.setCharacteristicNotification(characteristic,
+                            /*enable=*/false)
+                        bluetoothGatt.writeDescriptor(
+                            cccd,
+                            BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
+                        )
+                    }
+                }
             }
 
             override suspend fun awaitClose(onClosed: () -> Unit) {
@@ -198,6 +274,25 @@
                     onClosed()
                 }
             }
+
+            private fun registerSubscribeListener(
+                characteristic: BluetoothGattCharacteristic,
+                callback: SubscribeListener
+            ): Boolean {
+                synchronized(subscribeMap) {
+                    if (subscribeMap.containsKey(characteristic)) {
+                        return false
+                    }
+                    subscribeMap[characteristic] = callback
+                    return true
+                }
+            }
+
+            private fun unregisterSubscribeListener(characteristic: BluetoothGattCharacteristic) {
+                synchronized(subscribeMap) {
+                    subscribeMap.remove(characteristic)
+                }
+            }
         }
         coroutineScope {
             launch {
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
index 73c1935..e5f71ad 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
@@ -30,6 +30,7 @@
 import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.integration.testapp.R
 import androidx.bluetooth.integration.testapp.databinding.FragmentAdvertiserBinding
+import androidx.bluetooth.integration.testapp.ui.common.getColor
 import androidx.bluetooth.integration.testapp.ui.common.setViewEditText
 import androidx.bluetooth.integration.testapp.ui.common.toast
 import androidx.core.view.isVisible
@@ -63,12 +64,19 @@
             field = value
             if (value) {
                 _binding?.buttonAdvertise?.text = getString(R.string.stop_advertising)
+                _binding?.buttonAdvertise?.backgroundTintList = getColor(R.color.red_500)
             } else {
                 _binding?.buttonAdvertise?.text = getString(R.string.start_advertising)
+                _binding?.buttonAdvertise?.backgroundTintList = getColor(R.color.indigo_500)
                 advertiseJob?.cancel()
                 advertiseJob = null
             }
-            _binding?.viewOverlay?.isVisible = value
+            _binding?.textInputEditTextDisplayName?.isEnabled = !value
+            _binding?.checkBoxIncludeDeviceName?.isEnabled = !value
+            _binding?.checkBoxConnectable?.isEnabled = !value
+            _binding?.checkBoxDiscoverable?.isEnabled = !value
+            _binding?.buttonAddData?.isEnabled = !value
+            _binding?.viewRecyclerViewOverlay?.isVisible = value
         }
 
     private var _binding: FragmentAdvertiserBinding? = null
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/common/Fragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/common/Fragment.kt
index 395bd0d7..aaa4232 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/common/Fragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/common/Fragment.kt
@@ -16,9 +16,15 @@
 
 package androidx.bluetooth.integration.testapp.ui.common
 
+import android.content.res.ColorStateList
 import android.widget.Toast
+import androidx.core.content.ContextCompat
 import androidx.fragment.app.Fragment
 
+fun Fragment.getColor(color: Int): ColorStateList? {
+    return ContextCompat.getColorStateList(requireContext(), color)
+}
+
 fun Fragment.toast(msg: String): Toast {
     return Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT)
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/home/HomeFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/home/HomeFragment.kt
index 37c853b..593f46b 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/home/HomeFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/home/HomeFragment.kt
@@ -17,6 +17,7 @@
 package androidx.bluetooth.integration.testapp.ui.home
 
 import android.annotation.SuppressLint
+import android.bluetooth.BluetoothGattCharacteristic.PROPERTY_NOTIFY
 import android.bluetooth.BluetoothGattCharacteristic.PROPERTY_READ
 import android.bluetooth.le.AdvertiseData
 import android.bluetooth.le.AdvertiseSettings
@@ -39,6 +40,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.joinAll
 import kotlinx.coroutines.launch
 
@@ -150,14 +152,19 @@
                     val jobs = ArrayList<Job>()
                     for (srv in getServices()) {
                         for (char in srv.characteristics) {
-                            Log.d(TAG, "trying to read characteristic ${char.uuid}")
                             if (char.properties.and(PROPERTY_READ) == 0) continue
                             jobs.add(launch {
-                                val value = read(char).getOrNull()
+                                val value = readCharacteristic(char).getOrNull()
                                 if (value != null) {
                                     Log.d(TAG, "Successfully read characteristic value=$value")
                                 }
                             })
+                            if (char.properties.and(PROPERTY_NOTIFY) != 0) {
+                                jobs.add(launch {
+                                    val value = subscribeToCharacteristic(char).first()
+                                    Log.d(TAG, "Successfully get characteristic value=$value")
+                                })
+                            }
                         }
                     }
                     jobs.joinAll()
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/DeviceServicesAdapter.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/DeviceServicesAdapter.kt
new file mode 100644
index 0000000..8e5ab73
--- /dev/null
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/DeviceServicesAdapter.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.bluetooth.integration.testapp.ui.scanner
+
+// TODO(ofy) Migrate to androidx.bluetooth.BluetoothGattService once in place
+import android.bluetooth.BluetoothGattService
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.bluetooth.integration.testapp.R
+import androidx.recyclerview.widget.RecyclerView
+
+class DeviceServicesAdapter(var services: List<BluetoothGattService>) :
+    RecyclerView.Adapter<DeviceServicesAdapter.ViewHolder>() {
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val view = LayoutInflater.from(parent.context)
+            .inflate(R.layout.item_device_service, parent, false)
+        return ViewHolder(view)
+    }
+
+    override fun getItemCount(): Int {
+        return services.size
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val service = services[position]
+        holder.bind(service)
+    }
+
+    inner class ViewHolder(itemView: View) :
+        RecyclerView.ViewHolder(itemView) {
+
+        private val textViewUuid: TextView = itemView.findViewById(R.id.text_view_uuid)
+
+        fun bind(service: BluetoothGattService) {
+            textViewUuid.text = service.uuid.toString()
+        }
+    }
+}
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt
index 76d2284..76d6330 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt
@@ -23,27 +23,36 @@
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.TextView
 
 import androidx.bluetooth.integration.testapp.R
 import androidx.bluetooth.integration.testapp.databinding.FragmentScannerBinding
+import android.annotation.SuppressLint
+// TODO(ofy) Migrate to androidx.bluetooth.BluetoothDevice once in place
+// TODO(ofy) Migrate to androidx.bluetooth.BluetoothLe once scan API is in place
+import androidx.bluetooth.integration.testapp.experimental.BluetoothLe
+import androidx.bluetooth.integration.testapp.ui.common.getColor
+import androidx.core.view.isVisible
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 
-// TODO(ofy) Migrate to androidx.bluetooth.BluetoothLe once scan API is in place
-import androidx.bluetooth.integration.testapp.experimental.BluetoothLe
-import androidx.core.content.ContextCompat
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayout.Tab
 
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
+import java.lang.Exception
 
 class ScannerFragment : Fragment() {
 
     private companion object {
         private const val TAG = "ScannerFragment"
+
+        private const val TAB_RESULTS_POSITION = 0
     }
 
     private lateinit var scannerViewModel: ScannerViewModel
@@ -53,25 +62,50 @@
 
     private var scannerAdapter: ScannerAdapter? = null
 
+    private var deviceServicesAdapter: DeviceServicesAdapter? = null
+
     private val scanScope = CoroutineScope(Dispatchers.Main + Job())
     private var scanJob: Job? = null
 
+    private val connectScope = CoroutineScope(Dispatchers.Default + Job())
+    private var connectJob: Job? = null
+
     private var isScanning: Boolean = false
         set(value) {
             field = value
             if (value) {
                 _binding?.buttonScan?.text = getString(R.string.stop_scanning)
-                _binding?.buttonScan?.backgroundTintList =
-                    ContextCompat.getColorStateList(requireContext(), R.color.red_500)
+                _binding?.buttonScan?.backgroundTintList = getColor(R.color.red_500)
             } else {
                 _binding?.buttonScan?.text = getString(R.string.start_scanning)
-                _binding?.buttonScan?.backgroundTintList =
-                    ContextCompat.getColorStateList(requireContext(), R.color.indigo_500)
+                _binding?.buttonScan?.backgroundTintList = getColor(R.color.indigo_500)
                 scanJob?.cancel()
                 scanJob = null
             }
         }
 
+    private var showingScanResults: Boolean = false
+        set(value) {
+            field = value
+            _binding?.relativeLayoutScanResults?.isVisible = value
+            _binding?.linearLayoutDevice?.isVisible = !value
+        }
+
+    private val onTabSelectedListener = object : TabLayout.OnTabSelectedListener {
+        override fun onTabSelected(tab: Tab) {
+            showingScanResults = tab.position == TAB_RESULTS_POSITION
+            if (tab.position != TAB_RESULTS_POSITION) {
+                updateDeviceUI(scannerViewModel.deviceConnection(tab.position))
+            }
+        }
+
+        override fun onTabUnselected(tab: Tab) {
+        }
+
+        override fun onTabReselected(tab: Tab) {
+        }
+    }
+
     private var _binding: FragmentScannerBinding? = null
 
     // This property is only valid between onCreateView and onDestroyView.
@@ -88,12 +122,20 @@
 
         _binding = FragmentScannerBinding.inflate(inflater, container, false)
 
+        binding.tabLayout.addOnTabSelectedListener(onTabSelectedListener)
+
         scannerAdapter = ScannerAdapter { scanResult -> onClickScanResult(scanResult) }
         binding.recyclerViewScanResults.adapter = scannerAdapter
         binding.recyclerViewScanResults.addItemDecoration(
             DividerItemDecoration(context, LinearLayoutManager.VERTICAL)
         )
 
+        deviceServicesAdapter = DeviceServicesAdapter(emptyList())
+        binding.recyclerViewDeviceServices.adapter = deviceServicesAdapter
+        binding.recyclerViewDeviceServices.addItemDecoration(
+            DividerItemDecoration(context, LinearLayoutManager.VERTICAL)
+        )
+
         initData()
 
         binding.buttonScan.setOnClickListener {
@@ -111,11 +153,15 @@
         super.onDestroyView()
         _binding = null
         isScanning = false
+        scanJob?.cancel()
+        scanJob = null
     }
 
     private fun initData() {
         scannerAdapter?.submitList(scannerViewModel.results)
         scannerAdapter?.notifyItemRangeChanged(0, scannerViewModel.results.size)
+
+        scannerViewModel.devices.map { it.scanResult }.forEach(::addNewTab)
     }
 
     private fun startScan() {
@@ -139,6 +185,96 @@
     }
 
     private fun onClickScanResult(scanResult: ScanResult) {
-        Log.d(TAG, "onClickScanResult() called with: scanResult = $scanResult")
+        isScanning = false
+
+        val index = scannerViewModel.addDeviceConnectionIfNew(scanResult)
+
+        val deviceTab = if (index == ScannerViewModel.NEW_DEVICE) {
+            addNewTab(scanResult)
+        } else {
+            binding.tabLayout.getTabAt(index)
+        }
+
+        // To prevent TabSelectedListener being triggered when a tab is promatically selected.
+        binding.tabLayout.removeOnTabSelectedListener(onTabSelectedListener)
+        binding.tabLayout.selectTab(deviceTab)
+        binding.tabLayout.addOnTabSelectedListener(onTabSelectedListener)
+
+        showingScanResults = false
+
+        connectTo(scannerViewModel.deviceConnection(binding.tabLayout.selectedTabPosition))
+    }
+
+    @SuppressLint("MissingPermission")
+    private fun addNewTab(scanResult: ScanResult): Tab {
+        val deviceAddress = scanResult.device.address
+        val deviceName = scanResult.device.name
+
+        val newTab = binding.tabLayout.newTab()
+        newTab.setCustomView(R.layout.tab_item_device)
+
+        val customView = newTab.customView
+        customView?.findViewById<TextView>(R.id.text_view_address)?.text = deviceAddress
+        customView?.findViewById<TextView>(R.id.text_view_name)?.text = deviceName
+
+        binding.tabLayout.addTab(newTab)
+        return newTab
+    }
+
+    private fun connectTo(deviceConnection: DeviceConnection) {
+        Log.d(TAG, "connectTo() called with: deviceConnection = $deviceConnection")
+
+        connectJob = connectScope.launch {
+            deviceConnection.status = Status.CONNECTING
+            launch(Dispatchers.Main) {
+                updateDeviceUI(deviceConnection)
+            }
+
+            try {
+                bluetoothLe.connectGatt(requireContext(), deviceConnection.scanResult.device) {
+                    Log.d(TAG, "connectGatt result. getServices() = ${getServices()}")
+
+                    deviceConnection.status = Status.CONNECTED
+                    deviceConnection.services = getServices()
+                    launch(Dispatchers.Main) {
+                        updateDeviceUI(deviceConnection)
+                    }
+                }
+            } catch (exception: Exception) {
+                Log.e(TAG, "connectTo: exception", exception)
+
+                deviceConnection.status = Status.CONNECTION_FAILED
+                launch(Dispatchers.Main) {
+                    updateDeviceUI(deviceConnection)
+                }
+            }
+        }
+    }
+
+    @SuppressLint("NotifyDataSetChanged")
+    private fun updateDeviceUI(deviceConnection: DeviceConnection) {
+        binding.progressIndicatorDeviceConnection.isVisible = false
+
+        when (deviceConnection.status) {
+            Status.NOT_CONNECTED -> {
+                binding.textViewDeviceConnectionStatus.text = getString(R.string.not_connected)
+                binding.textViewDeviceConnectionStatus.setTextColor(getColor(R.color.green_500))
+            }
+            Status.CONNECTING -> {
+                binding.progressIndicatorDeviceConnection.isVisible = true
+                binding.textViewDeviceConnectionStatus.text = getString(R.string.connecting)
+                binding.textViewDeviceConnectionStatus.setTextColor(getColor(R.color.indigo_500))
+            }
+            Status.CONNECTED -> {
+                binding.textViewDeviceConnectionStatus.text = getString(R.string.connected)
+                binding.textViewDeviceConnectionStatus.setTextColor(getColor(R.color.indigo_500))
+            }
+            Status.CONNECTION_FAILED -> {
+                binding.textViewDeviceConnectionStatus.text = getString(R.string.connection_failed)
+                binding.textViewDeviceConnectionStatus.setTextColor(getColor(R.color.red_500))
+            }
+        }
+        deviceServicesAdapter?.services = deviceConnection.services
+        deviceServicesAdapter?.notifyDataSetChanged()
     }
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerViewModel.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerViewModel.kt
index 7d213fd..518fe42 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerViewModel.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerViewModel.kt
@@ -16,24 +16,60 @@
 
 package androidx.bluetooth.integration.testapp.ui.scanner
 
+// TODO(ofy) Migrate to androidx.bluetooth.ScanResult once in place
+import android.bluetooth.BluetoothGattService
 import android.bluetooth.le.ScanResult
 import androidx.lifecycle.ViewModel
 
 class ScannerViewModel : ViewModel() {
 
-    private companion object {
+    internal companion object {
         private const val TAG = "ScannerViewModel"
+
+        internal const val NEW_DEVICE = -1
     }
 
     internal val results: List<ScanResult> get() = _results.values.toList()
-
     private val _results = mutableMapOf<String, ScanResult>()
 
+    internal val devices: Set<DeviceConnection> get() = _devices
+    private val _devices = mutableSetOf<DeviceConnection>()
+
     fun addScanResultIfNew(scanResult: ScanResult): Boolean {
         val deviceAddress = scanResult.device.address
 
-        if (_results.containsKey(deviceAddress)) return false
+        if (_results.containsKey(deviceAddress)) {
+            return false
+        }
+
         _results[deviceAddress] = scanResult
         return true
     }
+
+    fun addDeviceConnectionIfNew(scanResult: ScanResult): Int {
+        val deviceConnection = DeviceConnection(scanResult)
+
+        val indexOf = _devices.map { it.scanResult }.indexOf(scanResult)
+        if (indexOf != -1) {
+            // Index 0 is Results page; Tabs for devices start from 1.
+            return indexOf + 1
+        }
+
+        _devices.add(deviceConnection)
+        return NEW_DEVICE
+    }
+
+    fun deviceConnection(position: Int): DeviceConnection {
+        // Index 0 is Results page; Tabs for devices start from 1.
+        return devices.elementAt(position - 1)
+    }
+}
+
+class DeviceConnection(val scanResult: ScanResult) {
+    var status = Status.NOT_CONNECTED
+    var services = emptyList<BluetoothGattService>()
+}
+
+enum class Status {
+    NOT_CONNECTED, CONNECTING, CONNECTED, CONNECTION_FAILED
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/res/drawable/baseline_add_24.xml b/bluetooth/integration-tests/testapp/src/main/res/drawable/baseline_add_24.xml
new file mode 100644
index 0000000..89633bb
--- /dev/null
+++ b/bluetooth/integration-tests/testapp/src/main/res/drawable/baseline_add_24.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml
index c6e37d3..014dc75 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml
@@ -88,12 +88,12 @@
 
     <Button
         android:id="@+id/button_add_data"
-        style="@style/Widget.AppCompat.Button.Borderless"
+        style="@style/Widget.MaterialComponents.Button.Icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="8dp"
         android:text="@string/add_data"
-        android:textColor="@color/purple_500"
+        app:icon="@drawable/baseline_add_24"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/text_view_advertising_data" />
 
@@ -108,12 +108,13 @@
         tools:listitem="@layout/item_advertiser_data" />
 
     <View
-        android:id="@+id/view_overlay"
+        android:id="@+id/view_recycler_view_overlay"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/black_alpha_50"
+        android:layout_height="0dp"
         android:clickable="true"
-        android:visibility="gone" />
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button_add_data" />
 
     <Button
         android:id="@+id/button_advertise"
diff --git a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml
index e27e808..9cf7c3484 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml
@@ -21,21 +21,97 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/recycler_view_scan_results"
+    <com.google.android.material.tabs.TabLayout
+        android:id="@+id/tab_layout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:layoutManager="LinearLayoutManager"
-        tools:itemCount="3"
-        tools:listitem="@layout/item_scan_result" />
-
-    <Button
-        android:id="@+id/button_scan"
-        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_margin="16dp"
-        android:text="@string/start_scanning"
+        app:layout_constraintTop_toTopOf="parent"
+        app:tabGravity="start"
+        app:tabMode="scrollable">
+
+        <com.google.android.material.tabs.TabItem
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/scan_results" />
+
+    </com.google.android.material.tabs.TabLayout>
+
+    <RelativeLayout
+        android:id="@+id/relative_layout_scan_results"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent" />
+        app:layout_constraintTop_toBottomOf="@+id/tab_layout"
+        tools:visibility="gone">
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recycler_view_scan_results"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:layoutManager="LinearLayoutManager"
+            tools:itemCount="3"
+            tools:listitem="@layout/item_scan_result" />
+
+        <Button
+            android:id="@+id/button_scan"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentEnd="true"
+            android:layout_alignParentBottom="true"
+            android:layout_margin="16dp"
+            android:text="@string/start_scanning" />
+
+    </RelativeLayout>
+
+    <LinearLayout
+        android:id="@+id/linear_layout_device"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:orientation="vertical"
+        android:padding="16dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tab_layout"
+        tools:visibility="visible">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical">
+
+            <TextView
+                android:id="@+id/text_view_device_connection_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:padding="8dp"
+                android:text="@string/not_connected"
+                android:textAllCaps="true"
+                android:textColor="@color/green_500"
+                android:textSize="16sp" />
+
+            <com.google.android.material.progressindicator.CircularProgressIndicator
+                android:id="@+id/progress_indicator_device_connection"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:indicatorSize="24dp" />
+
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="?android:attr/dividerVertical" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recycler_view_device_services"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:layoutManager="LinearLayoutManager"
+            tools:itemCount="3"
+            tools:listitem="@layout/item_device_service" />
+
+    </LinearLayout>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/layout/item_device_service.xml b/bluetooth/integration-tests/testapp/src/main/res/layout/item_device_service.xml
new file mode 100644
index 0000000..cb091804
--- /dev/null
+++ b/bluetooth/integration-tests/testapp/src/main/res/layout/item_device_service.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="8dp">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/generic_attribute"
+        android:textColor="#000000" />
+
+    <TextView
+        android:id="@+id/text_view_uuid"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        tools:text="UUID: 0x1800" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/primary_service"
+        android:textAllCaps="true" />
+
+</LinearLayout>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/layout/tab_item_device.xml b/bluetooth/integration-tests/testapp/src/main/res/layout/tab_item_device.xml
new file mode 100644
index 0000000..23880a4
--- /dev/null
+++ b/bluetooth/integration-tests/testapp/src/main/res/layout/tab_item_device.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  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.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/text_view_address"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="@color/black"
+        tools:text="70:04:13:03:98:B9" />
+
+    <TextView
+        android:id="@+id/text_view_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        tools:text="R33-0473" />
+
+</LinearLayout>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/values/colors.xml b/bluetooth/integration-tests/testapp/src/main/res/values/colors.xml
index 3fe5275..2b48616 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/values/colors.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/values/colors.xml
@@ -21,6 +21,4 @@
     <color name="green_500">#4CAF50</color>
     <color name="red_500">#F44336</color>
     <color name="black">#FF000000</color>
-    <color name="purple_500">#FF6200EE</color>
-    <color name="black_alpha_50">#80000000</color>
 </resources>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml b/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
index 5707c81..b6a131a 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
@@ -26,6 +26,13 @@
     <string name="stop_scanning">Stop scanning</string>
     <string name="scan_result_icon">Scan Result Icon</string>
     <string name="connect">Connect</string>
+    <string name="scan_results">Scan Results</string>
+    <string name="not_connected">Not Connected</string>
+    <string name="connecting">Connecting…</string>
+    <string name="connected">Connected</string>
+    <string name="connection_failed">Connection Failed</string>
+    <string name="generic_attribute">Generic Attribute</string>
+    <string name="primary_service">Primary Service</string>
 
     <!-- Advertiser -->
     <string name="configure_advertising_packet">Configure Advertising Packet</string>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/values/themes.xml b/bluetooth/integration-tests/testapp/src/main/res/values/themes.xml
index b1ee890..7ff92c0 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/values/themes.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/values/themes.xml
@@ -19,6 +19,6 @@
         <item name="colorPrimary">@color/indigo_500</item>
         <item name="colorPrimaryVariant">@color/indigo_700</item>
         <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
-        <item name="android:textColorPrimary">@color/white</item>
+        <item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.Dark.ActionBar</item>
     </style>
 </resources>
diff --git a/browser/browser/src/main/stableAidlImports/android/net/Uri.aidl b/browser/browser/src/main/stableAidlImports/android/net/Uri.aidl
deleted file mode 100644
index 5ec5a66..0000000
--- a/browser/browser/src/main/stableAidlImports/android/net/Uri.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.net;
-
-@JavaOnlyStableParcelable parcelable Uri;
diff --git a/browser/browser/src/main/stableAidlImports/android/os/Bundle.aidl b/browser/browser/src/main/stableAidlImports/android/os/Bundle.aidl
deleted file mode 100644
index 9642d31..0000000
--- a/browser/browser/src/main/stableAidlImports/android/os/Bundle.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.os;
-
-@JavaOnlyStableParcelable parcelable Bundle;
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
index f6ed376..1640305 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
@@ -80,12 +80,6 @@
 const val ENABLE_DOCUMENTATION = "androidx.enableDocumentation"
 
 /**
- * Adjusts the set of projects participating in this build.
- * See settings.gradle for more information
- */
-const val PROJECT_SUBSET = "androidx.projects"
-
-/**
  * Setting this property puts a summary of the relevant failure messages into standard error
  */
 const val SUMMARIZE_STANDARD_ERROR = "androidx.summarizeStderr"
@@ -167,7 +161,6 @@
     ENABLE_COMPOSE_COMPILER_REPORTS,
     DISPLAY_TEST_OUTPUT,
     ENABLE_DOCUMENTATION,
-    PROJECT_SUBSET,
     STUDIO_TYPE,
     SUMMARIZE_STANDARD_ERROR,
     USE_MAX_DEP_VERSIONS,
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index d42591b..f868506 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -45,6 +45,7 @@
 import com.android.build.api.variant.ApplicationAndroidComponentsExtension
 import com.android.build.api.variant.HasAndroidTest
 import com.android.build.api.variant.LibraryAndroidComponentsExtension
+import com.android.build.api.variant.Variant
 import com.android.build.gradle.AppExtension
 import com.android.build.gradle.AppPlugin
 import com.android.build.gradle.BaseExtension
@@ -329,7 +330,10 @@
         }
 
         project.extensions.getByType<ApplicationAndroidComponentsExtension>().apply {
-            onVariants { it.configureTests() }
+            onVariants {
+                it.configureTests()
+                it.artRewritingWorkaround()
+            }
             finalizeDsl {
                 project.configureAndroidProjectForLint(
                     it.lint,
@@ -358,6 +362,14 @@
         excludeVersionFilesFromTestApks()
     }
 
+    private fun Variant.artRewritingWorkaround() {
+        // b/279234807
+        experimentalProperties.put(
+            "android.experimental.art-profile-r8-rewriting",
+            false
+        )
+    }
+
     private fun HasAndroidTest.configureLicensePackaging() {
         androidTest?.packaging?.resources?.apply {
             // Workaround a limitation in AGP that fails to merge these META-INF license files.
@@ -443,7 +455,10 @@
             beforeVariants(selector().withBuildType("release")) { variant ->
                 variant.enableUnitTest = false
             }
-            onVariants { it.configureTests() }
+            onVariants {
+                it.configureTests()
+                it.artRewritingWorkaround()
+            }
             finalizeDsl {
                 project.configureAndroidProjectForLint(it.lint, androidXExtension, isLibrary = true)
             }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/ProjectResolver.kt b/buildSrc/private/src/main/kotlin/androidx/build/ProjectResolver.kt
index 4b207e8..65f0428 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/ProjectResolver.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/ProjectResolver.kt
@@ -45,13 +45,8 @@
  * in the build, to make project configuration run more quickly.
  */
 fun Project.getProjectSubset(): String? {
-    val prop = project.providers.gradleProperty("androidx.projects")
-    if (prop.isPresent()) {
-        return prop.get().uppercase()
-    }
-
     val envProp = project.providers.environmentVariable("ANDROIDX_PROJECTS")
-    if (envProp.isPresent()) {
+    if (envProp.isPresent) {
         return envProp.get().uppercase()
     }
     return null
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiLocation.kt b/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiLocation.kt
index d9587ea..0f22c64 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiLocation.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiLocation.kt
@@ -56,7 +56,9 @@
     // File where the library's public resources are recorded
     val resourceFile: File,
     // Directory where native API files are stored
-    val nativeApiDirectory: File
+    val nativeApiDirectory: File,
+    // Directory where the library's stable AIDL surface is recorded
+    val aidlApiDirectory: File
 ) : Serializable {
 
     /**
@@ -96,7 +98,8 @@
                 restrictedApiFile = File(apiFileDir, "$PREFIX_RESTRICTED$baseName$EXTENSION"),
                 experimentalApiFile = File(apiFileDir, "$PREFIX_EXPERIMENTAL$baseName$EXTENSION"),
                 resourceFile = File(apiFileDir, "$PREFIX_RESOURCE$baseName$EXTENSION"),
-                nativeApiDirectory = File(apiFileDir, NATIVE_API_DIRECTORY_NAME).resolve(baseName)
+                nativeApiDirectory = File(apiFileDir, NATIVE_API_DIRECTORY_NAME).resolve(baseName),
+                aidlApiDirectory = File(apiFileDir, AIDL_API_DIRECTORY_NAME).resolve(baseName)
             )
         }
 
@@ -134,6 +137,11 @@
          * Directory name for location of native API files
          */
         private const val NATIVE_API_DIRECTORY_NAME = "native"
+
+        /**
+         * Directory name for location of AIDL API files
+         */
+        private const val AIDL_API_DIRECTORY_NAME = "aidl"
     }
 }
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt b/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt
index 708cd58..84ef383 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt
@@ -26,6 +26,7 @@
 import androidx.build.libabigail.NativeApiTasks
 import androidx.build.metalava.MetalavaTasks
 import androidx.build.resources.ResourceTasks
+import androidx.build.stableaidl.setupWithStableAidlPlugin
 import androidx.build.version
 import com.android.build.gradle.LibraryExtension
 import com.android.build.gradle.tasks.ProcessLibraryManifest
@@ -198,6 +199,8 @@
             )
         }
 
+        project.setupWithStableAidlPlugin()
+
         if (config is LibraryApiTaskConfig) {
             ResourceTasks.setupProject(
                 project, Release.DEFAULT_PUBLISH_CONFIG,
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
index 0286efc..b900386 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
@@ -18,6 +18,9 @@
 
 import androidx.build.checkapi.ApiLocation
 import com.google.common.io.Files
+import java.io.File
+import java.security.MessageDigest
+import org.apache.commons.io.FileUtils
 import org.gradle.api.DefaultTask
 import org.gradle.api.GradleException
 import org.gradle.api.logging.Logger
@@ -25,14 +28,13 @@
 import org.gradle.api.provider.Property
 import org.gradle.api.tasks.CacheableTask
 import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
 import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Optional
 import org.gradle.api.tasks.OutputFiles
 import org.gradle.api.tasks.PathSensitive
 import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.TaskAction
-import java.io.File
-import org.gradle.api.tasks.Optional
 import org.gradle.api.tasks.options.Option
 
 /**
@@ -189,6 +191,54 @@
     }
 }
 
+fun copyDir(
+    source: File,
+    dest: File,
+    permitOverwriting: Boolean,
+    logger: Logger
+) {
+    val sourceHash = if (source.exists()) {
+        hashDir(source)
+    } else {
+        null
+    }
+    val overwriting = dest.exists() && !sourceHash.contentEquals(hashDir(dest))
+    val changing = overwriting || (dest.exists() != source.exists())
+    if (changing) {
+        if (overwriting && !permitOverwriting) {
+            val message = "Modifying the API definition for a previously released artifact " +
+                "having a final API version (version not ending in '-alpha') is not " +
+                "allowed.\n\n" +
+                "Previously declared definition is $dest\n" +
+                "Current generated   definition is $source\n\n" +
+                "Did you mean to increment the library version first?\n\n" +
+                "If you have reason to overwrite the API files for the previous release " +
+                "anyway, you can run `./gradlew updateApi -Pforce` to ignore this message"
+            throw GradleException(message)
+        }
+        FileUtils.deleteDirectory(dest)
+        if (source.exists()) {
+            FileUtils.copyDirectory(source, dest)
+            logger.lifecycle("Copied $source to $dest")
+        } else {
+            logger.lifecycle("Deleted $dest because $source does not exist")
+        }
+    }
+}
+
+fun hashDir(dir: File): ByteArray {
+    val digest = MessageDigest.getInstance("SHA-256")
+    dir.listFiles()?.forEach { file ->
+        val fileBytes = if (file.isDirectory) {
+            hashDir(file)
+        } else {
+            file.readBytes()
+        }
+        digest.update(fileBytes)
+    }
+    return digest.digest()
+}
+
 /**
  * Returns -1 if [text] has fewer than [count] newline characters, 0 if equal, and 1 if greater
  * than.
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/stableaidl/StableAidlApiTasks.kt b/buildSrc/private/src/main/kotlin/androidx/build/stableaidl/StableAidlApiTasks.kt
new file mode 100644
index 0000000..f700913
--- /dev/null
+++ b/buildSrc/private/src/main/kotlin/androidx/build/stableaidl/StableAidlApiTasks.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 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.build.stableaidl
+
+import androidx.build.BUILD_ON_SERVER_TASK
+import androidx.build.getSupportRootFolder
+import androidx.stableaidl.withStableAidlPlugin
+import java.io.File
+import org.gradle.api.Project
+
+fun Project.setupWithStableAidlPlugin() = this.withStableAidlPlugin { ext ->
+    ext.checkAction.apply {
+        before(project.tasks.named("check"))
+        before(project.tasks.named(BUILD_ON_SERVER_TASK))
+        before(project.tasks.register("checkAidlApi") { task ->
+            task.group = "API"
+            task.description = "Checks that the API surface generated Stable AIDL sources " +
+                "matches the checked in API surface"
+        })
+    }
+
+    ext.updateAction.apply {
+        before(project.tasks.named("updateApi"))
+        before(project.tasks.register("updateAidlApi") { task ->
+            task.group = "API"
+            task.description = "Updates the checked in API surface based on Stable AIDL sources"
+        })
+    }
+
+    // Don't show tasks added by the Stable AIDL plugin.
+    ext.taskGroup = null
+
+    // Use a single top-level directory for shadow framework definitions.
+    ext.addStaticImportDirs(
+        File(project.getSupportRootFolder(), "buildSrc/stableAidlImports")
+    )
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/studio/StudioTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/studio/StudioTask.kt
index 4b9fe1c..8e922b1 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/studio/StudioTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/studio/StudioTask.kt
@@ -22,8 +22,6 @@
 import androidx.build.getSdkPath
 import androidx.build.getSupportRootFolder
 import androidx.build.getVersionByName
-import androidx.build.hasSupportRootFolder
-import androidx.build.setSupportRootFolder
 import com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
 import java.io.File
 import java.nio.file.Files
@@ -125,6 +123,12 @@
     open val vmOptions = File(project.getSupportRootFolder(), "development/studio/studio.vmoptions")
 
     /**
+     * The path to the SDK directory used by Studio.
+     */
+    @get:Internal
+    open val localSdkPath = project.getSdkPath()
+
+    /**
      * List of additional environment variables to pass into the Studio application.
      */
     @get:Internal
@@ -179,18 +183,6 @@
      */
     private fun setupSymlinksIfNeeded() {
         val paths = listOf("system-images", "emulator")
-
-        // The support root folder may not have been set yet, in which case we'll optimistically
-        // assume that it matches the root project. This won't work for ui or Playground, but we'll
-        // fail gracefully later.
-        val hadSupportRootFolder = project.hasSupportRootFolder()
-        if (!hadSupportRootFolder) {
-            project.setSupportRootFolder(project.rootDir)
-        }
-        val localSdkPath = project.getSdkPath()
-        if (!hadSupportRootFolder) {
-            project.setSupportRootFolder(null)
-        }
         if (!localSdkPath.exists()) {
             // We probably got the support root folder wrong. Fail gracefully.
             return
@@ -229,11 +221,15 @@
      */
     private fun launch() {
         if (checkLicenseAgreement(services)) {
-            if (requiresProjectList && !System.getenv().containsKey("ANDROIDX_PROJECTS")) {
+            if (requiresProjectList &&
+                !System.getenv().containsKey("ANDROIDX_PROJECTS") &&
+                !System.getenv().containsKey("PROJECT_PREFIX")
+                ) {
                 throw GradleException(
                     """
                     Please specify which set of projects you'd like to open in studio
                     with ANDROIDX_PROJECTS=MAIN ./gradlew studio
+                    or PROJECT_PREFIX=:room: ./gradlew studio
 
                     For possible options see settings.gradle
                     """.trimIndent()
diff --git a/core/core/src/main/stableAidlImports/android/app/Notification.aidl b/buildSrc/stableAidlImports/android/app/Notification.aidl
similarity index 100%
rename from core/core/src/main/stableAidlImports/android/app/Notification.aidl
rename to buildSrc/stableAidlImports/android/app/Notification.aidl
diff --git a/media/media/src/main/stableAidlImports/android/app/PendingIntent.aidl b/buildSrc/stableAidlImports/android/app/PendingIntent.aidl
similarity index 100%
rename from media/media/src/main/stableAidlImports/android/app/PendingIntent.aidl
rename to buildSrc/stableAidlImports/android/app/PendingIntent.aidl
diff --git a/browser/browser/src/main/stableAidlImports/android/content/ComponentName.aidl b/buildSrc/stableAidlImports/android/content/ComponentName.aidl
similarity index 100%
rename from browser/browser/src/main/stableAidlImports/android/content/ComponentName.aidl
rename to buildSrc/stableAidlImports/android/content/ComponentName.aidl
diff --git a/car/app/app/src/main/stableAidlImports/android/content/Intent.aidl b/buildSrc/stableAidlImports/android/content/Intent.aidl
similarity index 100%
rename from car/app/app/src/main/stableAidlImports/android/content/Intent.aidl
rename to buildSrc/stableAidlImports/android/content/Intent.aidl
diff --git a/javascriptengine/javascriptengine/src/main/stableAidlImports/android/content/res/AssetFileDescriptor.aidl b/buildSrc/stableAidlImports/android/content/res/AssetFileDescriptor.aidl
similarity index 100%
rename from javascriptengine/javascriptengine/src/main/stableAidlImports/android/content/res/AssetFileDescriptor.aidl
rename to buildSrc/stableAidlImports/android/content/res/AssetFileDescriptor.aidl
diff --git a/car/app/app/src/main/stableAidlImports/android/content/res/Configuration.aidl b/buildSrc/stableAidlImports/android/content/res/Configuration.aidl
similarity index 100%
rename from car/app/app/src/main/stableAidlImports/android/content/res/Configuration.aidl
rename to buildSrc/stableAidlImports/android/content/res/Configuration.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/graphics/Insets.aidl b/buildSrc/stableAidlImports/android/graphics/Insets.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/graphics/Insets.aidl
rename to buildSrc/stableAidlImports/android/graphics/Insets.aidl
diff --git a/car/app/app/src/main/stableAidlImports/android/graphics/Rect.aidl b/buildSrc/stableAidlImports/android/graphics/Rect.aidl
similarity index 100%
rename from car/app/app/src/main/stableAidlImports/android/graphics/Rect.aidl
rename to buildSrc/stableAidlImports/android/graphics/Rect.aidl
diff --git a/car/app/app/src/main/stableAidlImports/android/location/Location.aidl b/buildSrc/stableAidlImports/android/location/Location.aidl
similarity index 100%
rename from car/app/app/src/main/stableAidlImports/android/location/Location.aidl
rename to buildSrc/stableAidlImports/android/location/Location.aidl
diff --git a/media/media/src/main/stableAidlImports/android/net/Uri.aidl b/buildSrc/stableAidlImports/android/net/Uri.aidl
similarity index 100%
rename from media/media/src/main/stableAidlImports/android/net/Uri.aidl
rename to buildSrc/stableAidlImports/android/net/Uri.aidl
diff --git a/core/core/src/main/stableAidlImports/android/os/Bundle.aidl b/buildSrc/stableAidlImports/android/os/Bundle.aidl
similarity index 100%
rename from core/core/src/main/stableAidlImports/android/os/Bundle.aidl
rename to buildSrc/stableAidlImports/android/os/Bundle.aidl
diff --git a/car/app/app-projected/src/main/stableAidlImports/android/os/IBinder.aidl b/buildSrc/stableAidlImports/android/os/IBinder.aidl
similarity index 100%
rename from car/app/app-projected/src/main/stableAidlImports/android/os/IBinder.aidl
rename to buildSrc/stableAidlImports/android/os/IBinder.aidl
diff --git a/media/media/src/main/stableAidlImports/android/view/KeyEvent.aidl b/buildSrc/stableAidlImports/android/view/KeyEvent.aidl
similarity index 100%
rename from media/media/src/main/stableAidlImports/android/view/KeyEvent.aidl
rename to buildSrc/stableAidlImports/android/view/KeyEvent.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/MotionEvent.aidl b/buildSrc/stableAidlImports/android/view/MotionEvent.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/MotionEvent.aidl
rename to buildSrc/stableAidlImports/android/view/MotionEvent.aidl
diff --git a/media2/media2-session/src/main/stableAidlImports/android/view/Surface.aidl b/buildSrc/stableAidlImports/android/view/Surface.aidl
similarity index 100%
rename from media2/media2-session/src/main/stableAidlImports/android/view/Surface.aidl
rename to buildSrc/stableAidlImports/android/view/Surface.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/CompletionInfo.aidl b/buildSrc/stableAidlImports/android/view/inputmethod/CompletionInfo.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/CompletionInfo.aidl
rename to buildSrc/stableAidlImports/android/view/inputmethod/CompletionInfo.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/CorrectionInfo.aidl b/buildSrc/stableAidlImports/android/view/inputmethod/CorrectionInfo.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/CorrectionInfo.aidl
rename to buildSrc/stableAidlImports/android/view/inputmethod/CorrectionInfo.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/EditorInfo.aidl b/buildSrc/stableAidlImports/android/view/inputmethod/EditorInfo.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/EditorInfo.aidl
rename to buildSrc/stableAidlImports/android/view/inputmethod/EditorInfo.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/ExtractedText.aidl b/buildSrc/stableAidlImports/android/view/inputmethod/ExtractedText.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/ExtractedText.aidl
rename to buildSrc/stableAidlImports/android/view/inputmethod/ExtractedText.aidl
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/ExtractedTextRequest.aidl b/buildSrc/stableAidlImports/android/view/inputmethod/ExtractedTextRequest.aidl
similarity index 100%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/inputmethod/ExtractedTextRequest.aidl
rename to buildSrc/stableAidlImports/android/view/inputmethod/ExtractedTextRequest.aidl
diff --git a/busytown/androidx_multiplatform.sh b/busytown/androidx_multiplatform.sh
new file mode 120000
index 0000000..e2a6ac8
--- /dev/null
+++ b/busytown/androidx_multiplatform.sh
@@ -0,0 +1 @@
+./androidx_compose_multiplatform.sh
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt
index 3ce18a3..a072374 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt
@@ -296,9 +296,6 @@
         val action = FocusMeteringAction.Builder(factory.createPoint(0f, 0f)).build()
         bindUseCase(imageAnalysis)
 
-        // TODO(b/269968191): wait till camera is ready for submitting requests
-        waitForResult(1).verify({ _, _ -> true }, TIMEOUT)
-
         // Act.
         cameraControl.startFocusAndMetering(action).await()
 
@@ -345,9 +342,6 @@
         val action = FocusMeteringAction.Builder(factory.createPoint(0f, 0f)).build()
         bindUseCase(imageAnalysis)
 
-        // TODO(b/269968191): wait till camera is ready for submitting requests
-        waitForResult(1).verify({ _, _ -> true }, TIMEOUT)
-
         // Act.
         cameraControl.startFocusAndMetering(action).await()
         cameraControl.cancelFocusAndMetering().await()
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/testing/TestUseCaseCamera.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/testing/TestUseCaseCamera.kt
index d5795f9..5ed3f28 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/testing/TestUseCaseCamera.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/testing/TestUseCaseCamera.kt
@@ -19,6 +19,7 @@
 package androidx.camera.camera2.pipe.testing
 
 import android.content.Context
+import android.hardware.camera2.CameraCharacteristics
 import android.hardware.camera2.CameraDevice
 import android.hardware.camera2.CaptureRequest
 import androidx.annotation.RequiresApi
@@ -30,7 +31,10 @@
 import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
 import androidx.camera.camera2.pipe.integration.adapter.CaptureConfigAdapter
 import androidx.camera.camera2.pipe.integration.adapter.SessionConfigAdapter
+import androidx.camera.camera2.pipe.integration.compat.StreamConfigurationMapCompat
+import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
 import androidx.camera.camera2.pipe.integration.compat.workaround.NoOpInactiveSurfaceCloser
+import androidx.camera.camera2.pipe.integration.compat.workaround.OutputSizesCorrector
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraConfig
 import androidx.camera.camera2.pipe.integration.impl.CameraCallbackMap
@@ -68,10 +72,22 @@
         NoOpInactiveSurfaceCloser,
     ),
 ) : UseCaseCamera {
+    val cameraMetadata =
+        cameraPipe.cameras().awaitCameraMetadata(CameraId.fromCamera2Id(cameraId))!!
+    val streamConfigurationMap =
+        cameraMetadata[CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP]
+    val cameraQuirks = CameraQuirks(
+        cameraMetadata,
+        StreamConfigurationMapCompat(
+            streamConfigurationMap,
+            OutputSizesCorrector(cameraMetadata, streamConfigurationMap)
+        )
+    )
     val useCaseCameraGraphConfig =
         UseCaseCameraConfig(
             useCases,
             CameraStateAdapter(),
+            cameraQuirks,
             CameraGraph.Flags()
         ).provideUseCaseGraphConfig(
             callbackMap = callbackMap,
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt
index d80d27a..71ea477 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt
@@ -62,9 +62,18 @@
         if (CameraNoResponseWhenEnablingFlashQuirk.isEnabled(cameraMetadata)) {
             quirks.add(CameraNoResponseWhenEnablingFlashQuirk())
         }
+        if (CaptureSessionStuckQuirk.isEnabled()) {
+            quirks.add(CaptureSessionStuckQuirk())
+        }
+        if (CloseCaptureSessionOnVideoQuirk.isEnabled()) {
+            quirks.add(CloseCaptureSessionOnVideoQuirk())
+        }
         if (ConfigureSurfaceToSecondarySessionFailQuirk.isEnabled(cameraMetadata)) {
             quirks.add(ConfigureSurfaceToSecondarySessionFailQuirk())
         }
+        if (FinalizeSessionOnCloseQuirk.isEnabled()) {
+            quirks.add(FinalizeSessionOnCloseQuirk())
+        }
         if (FlashTooSlowQuirk.isEnabled(cameraMetadata)) {
             quirks.add(FlashTooSlowQuirk())
         }
@@ -92,13 +101,13 @@
         if (YuvImageOnePixelShiftQuirk.isEnabled()) {
             quirks.add(YuvImageOnePixelShiftQuirk())
         }
-        if (CaptureSessionStuckQuirk.isEnabled()) {
-            quirks.add(CaptureSessionStuckQuirk())
-        }
-        if (FinalizeSessionOnCloseQuirk.isEnabled()) {
-            quirks.add(FinalizeSessionOnCloseQuirk())
-        }
 
         Quirks(quirks)
     }
+
+    companion object {
+        fun isImmediateSurfaceReleaseAllowed(): Boolean {
+            return Build.BRAND == "google"
+        }
+    }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CloseCaptureSessionOnVideoQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CloseCaptureSessionOnVideoQuirk.kt
new file mode 100644
index 0000000..caad5f5
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CloseCaptureSessionOnVideoQuirk.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.camera.camera2.pipe.integration.compat.quirk
+
+import android.annotation.SuppressLint
+import androidx.annotation.RequiresApi
+import androidx.camera.core.impl.Quirk
+
+/**
+ * A quirk that instructs the CameraGraph to close the capture session when it is stopped or closed.
+ *
+ * QuirkSummary
+ * - Bug Id:      277310425
+ * - Description: When we unbind and rebind a VideoCapture use case, the video setup process waits
+ *                for the Surfaces to be released. This creates a potential deadlock, as CameraPipe
+ *                may not release the Surfaces if the previous session or camera remains unclosed.
+ *                This is a quirk added so that when we create a CameraGraph out of a set of use
+ *                cases with VideoCapture, we make sure we explicitly instruct CameraGraph to close
+ *                the capture session when the graph is closed.
+ * - Device(s):   All devices.
+ */
+@SuppressLint("CameraXQuirksClassDetector")
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+class CloseCaptureSessionOnVideoQuirk : Quirk {
+    companion object {
+        fun isEnabled(): Boolean = true
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/FinalizeSessionOnCloseQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/FinalizeSessionOnCloseQuirk.kt
index 95a6727..ed333d1 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/FinalizeSessionOnCloseQuirk.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/FinalizeSessionOnCloseQuirk.kt
@@ -44,11 +44,19 @@
         fun isEnabled() = true
 
         fun getBehavior() =
-            if (Build.BRAND == "google") {
+            if (CameraQuirks.isImmediateSurfaceReleaseAllowed()) {
                 // Finalize immediately for devices that allow immediate Surface reuse.
                 FinalizeSessionOnCloseBehavior.IMMEDIATE
-            } else {
+            } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+                // When CloseCaptureSessionOnVideoQuirk is enabled, we close the capture session
+                // in anticipation that the onClosed() callback would finalize the session. However,
+                // on API levels < M, it could be possible that onClosed() isn't invoked if a new
+                // capture session (or CameraGraph) is created too soon (read b/144817309 or
+                // CaptureSessionOnClosedNotCalledQuirk for more context). Therefore, we're enabling
+                // this quirk (on a timeout) for API levels < M, too.
                 FinalizeSessionOnCloseBehavior.TIMEOUT
+            } else {
+                FinalizeSessionOnCloseBehavior.OFF
             }
     }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt
index 0a3c631..dac86b9 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt
@@ -28,12 +28,13 @@
  * Quirk denoting the video profile list returns by [EncoderProfiles] is invalid.
  *
  * QuirkSummary
- * - Bug Id: 267727595
+ * - Bug Id: 267727595, 278860860
  * - Description: When using [EncoderProfiles] on TP1A or TD1A builds of Android API 33,
  *   [EncoderProfiles.getVideoProfiles] returns a list with size one, but the single value in the
  *   list is null. This is not the expected behavior, and makes [EncoderProfiles] lack of video
  *   information.
- * - Device(s): Pixel 4 and above pixel devices with TP1A or TD1A builds (API 33).
+ * - Device(s): Pixel 4 and above pixel devices with TP1A or TD1A builds (API 33), Samsung devices
+ *              with TP1A build (API 33).
  *
  * TODO: enable CameraXQuirksClassDetector lint check when kotlin is supported.
  */
@@ -41,7 +42,7 @@
 class InvalidVideoProfilesQuirk : Quirk {
 
     companion object {
-        private val AFFECTED_MODELS: List<String> = listOf(
+        private val AFFECTED_PIXEL_MODELS: List<String> = listOf(
             "pixel 4",
             "pixel 4a",
             "pixel 4a (5g)",
@@ -56,25 +57,33 @@
         )
 
         fun isEnabled(): Boolean {
-            return isAffectedModel() && isAffectedBuild()
+            return isAffectedSamsungDevices() || isAffectedPixelDevices()
         }
 
-        private fun isAffectedModel(): Boolean {
-            return AFFECTED_MODELS.contains(
+        private fun isAffectedSamsungDevices(): Boolean {
+            return "samsung".equals(Build.BRAND, true) && isTp1aBuild()
+        }
+
+        private fun isAffectedPixelDevices(): Boolean {
+            return isAffectedPixelModel() && isAffectedPixelBuild()
+        }
+
+        private fun isAffectedPixelModel(): Boolean {
+            return AFFECTED_PIXEL_MODELS.contains(
                 Build.MODEL.lowercase()
             )
         }
 
-        private fun isAffectedBuild(): Boolean {
+        private fun isAffectedPixelBuild(): Boolean {
             return isTp1aBuild() || isTd1aBuild()
         }
 
         private fun isTp1aBuild(): Boolean {
-            return Build.ID.startsWith("TP1A")
+            return Build.ID.startsWith("TP1A", true)
         }
 
         private fun isTd1aBuild(): Boolean {
-            return Build.ID.startsWith("TD1A")
+            return Build.ID.startsWith("TD1A", true)
         }
     }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/UseCaseCameraConfig.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/UseCaseCameraConfig.kt
index d8e75a8..e05349a1 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/UseCaseCameraConfig.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/UseCaseCameraConfig.kt
@@ -18,6 +18,7 @@
 
 package androidx.camera.camera2.pipe.integration.config
 
+import android.media.MediaCodec
 import androidx.annotation.RequiresApi
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraId
@@ -30,6 +31,8 @@
 import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
 import androidx.camera.camera2.pipe.integration.adapter.SessionConfigAdapter
 import androidx.camera.camera2.pipe.integration.adapter.SessionConfigAdapter.Companion.toCamera2ImplConfig
+import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
+import androidx.camera.camera2.pipe.integration.compat.quirk.CloseCaptureSessionOnVideoQuirk
 import androidx.camera.camera2.pipe.integration.compat.workaround.CapturePipelineTorchCorrection
 import androidx.camera.camera2.pipe.integration.impl.CameraCallbackMap
 import androidx.camera.camera2.pipe.integration.impl.CameraInteropStateCallbackRepository
@@ -82,6 +85,7 @@
 class UseCaseCameraConfig(
     private val useCases: List<UseCase>,
     private val cameraStateAdapter: CameraStateAdapter,
+    private val cameraQuirks: CameraQuirks,
     private val cameraGraphFlags: CameraGraph.Flags,
 ) {
     @UseCaseCameraScope
@@ -106,6 +110,7 @@
     ): UseCaseGraphConfig {
         val streamConfigMap = mutableMapOf<CameraStream.Config, DeferrableSurface>()
 
+        var containsVideo = false
         // TODO: This may need to combine outputs that are (or will) share the same output
         //  imageReader or surface.
         val sessionConfigAdapter = SessionConfigAdapter(useCases)
@@ -134,9 +139,26 @@
                     "Prepare config for: $deferrableSurface (${deferrableSurface.prescribedSize}," +
                         " ${deferrableSurface.prescribedStreamFormat})"
                 }
+                if (deferrableSurface.containerClass == MediaCodec::class.java) {
+                    containsVideo = true
+                }
             }
         }
 
+        val shouldCloseCaptureSessionOnDisconnect =
+            if (CameraQuirks.isImmediateSurfaceReleaseAllowed()) {
+                // If we can release Surfaces immediately, we'll finalize the session when the
+                // camera graph is closed (through FinalizeSessionOnCloseQuirk), and thus we won't
+                // need to explicitly close the capture session.
+                false
+            } else {
+                cameraQuirks.quirks.contains(CloseCaptureSessionOnVideoQuirk::class.java) &&
+                    containsVideo
+            }
+        val combinedFlags = cameraGraphFlags.copy(
+            quirkCloseCaptureSessionOnDisconnect = shouldCloseCaptureSessionOnDisconnect,
+        )
+
         // Build up a config (using TEMPLATE_PREVIEW by default)
         // TODO(b/277310425): Turn off CameraGraph.Flags.quirkFinalizeSessionOnCloseBehavior when
         //  it's not needed. This should be needed only when all use cases are detached (with
@@ -146,7 +168,7 @@
                 camera = cameraConfig.cameraId,
                 streams = streamConfigMap.keys.toList(),
                 defaultListeners = listOf(callbackMap, requestListener),
-                flags = cameraGraphFlags,
+                flags = combinedFlags,
             )
         )
 
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraCallbackMap.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraCallbackMap.kt
index a19f296..6929c99 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraCallbackMap.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraCallbackMap.kt
@@ -32,7 +32,6 @@
 import androidx.camera.camera2.pipe.Request
 import androidx.camera.camera2.pipe.RequestMetadata
 import androidx.camera.camera2.pipe.StreamId
-import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.camera2.pipe.integration.adapter.CameraUseCaseAdapter
 import androidx.camera.camera2.pipe.integration.adapter.CaptureResultAdapter
 import androidx.camera.camera2.pipe.integration.config.CameraScope
@@ -88,8 +87,6 @@
                         )
                     }
                 }
-            } else {
-                Log.error { "Unhandled callback for onBufferLost()" }
             }
         }
     }
@@ -209,8 +206,6 @@
                         )
                     }
                 }
-            } else {
-                Log.error { "Unhandled callback for onRequestSequenceCompleted()" }
             }
         }
     }
@@ -232,8 +227,6 @@
                         )
                     }
                 }
-            } else {
-                Log.error { "Unhandled callback for onStarted()" }
             }
         }
     }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt
index bfa1fc7..beb29c8 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt
@@ -34,6 +34,7 @@
 import androidx.camera.camera2.pipe.Result3A
 import androidx.camera.camera2.pipe.StreamId
 import androidx.camera.camera2.pipe.TorchState
+import androidx.camera.camera2.pipe.core.Log.debug
 import androidx.camera.camera2.pipe.integration.adapter.CaptureConfigAdapter
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraScope
 import androidx.camera.camera2.pipe.integration.config.UseCaseGraphConfig
@@ -179,6 +180,7 @@
         tags: Map<String, Any>,
         listeners: Set<Request.Listener>
     ): Deferred<Unit> = synchronized(lock) {
+        debug { "[$type] Add request option: $values" }
         infoBundleMap.getOrPut(type) { InfoBundle() }.let {
             it.options.addAllCaptureRequestOptionsWithPriority(values, optionPriority)
             it.tags.putAll(tags)
@@ -195,6 +197,7 @@
         template: RequestTemplate?,
         listeners: Set<Request.Listener>
     ): Deferred<Unit> = synchronized(lock) {
+        debug { "[$type] Set config: ${config?.toParameters()}" }
         infoBundleMap[type] = InfoBundle(
             Camera2ImplConfig.Builder().apply {
                 config?.let {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt
index 57cfef6..ddf68c2 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt
@@ -29,6 +29,7 @@
 import androidx.camera.camera2.pipe.RequestMetadata
 import androidx.camera.camera2.pipe.RequestTemplate
 import androidx.camera.camera2.pipe.StreamId
+import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraScope
 import androidx.camera.camera2.pipe.integration.config.UseCaseGraphConfig
 import javax.inject.Inject
@@ -254,7 +255,7 @@
                     result?.let { result ->
                         updateSignals.add(RequestSignal(submittedRequestCounter.value, result))
                     }
-
+                    Log.debug { "Update RepeatingRequest: $request" }
                     it.startRepeating(request)
                 }
             }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index 222047d..9f39981 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -23,6 +23,7 @@
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
+import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
 import androidx.camera.camera2.pipe.integration.config.CameraScope
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraComponent
@@ -72,6 +73,7 @@
     private val controls: java.util.Set<UseCaseCameraControl>,
     private val camera2CameraControl: Camera2CameraControl,
     private val cameraStateAdapter: CameraStateAdapter,
+    private val cameraQuirks: CameraQuirks,
     private val cameraGraphFlags: CameraGraph.Flags,
     cameraProperties: CameraProperties,
     displayInfoManager: DisplayInfoManager,
@@ -257,7 +259,14 @@
 
         // Create and configure the new camera component.
         _activeComponent =
-            builder.config(UseCaseCameraConfig(useCases, cameraStateAdapter, cameraGraphFlags))
+            builder.config(
+                UseCaseCameraConfig(
+                    useCases,
+                    cameraStateAdapter,
+                    cameraQuirks,
+                    cameraGraphFlags
+                )
+            )
                 .build()
         for (control in allControls) {
             control.useCaseCamera = camera
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
index f0a9f17..58e25df 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
@@ -22,6 +22,9 @@
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
 import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
+import androidx.camera.camera2.pipe.integration.compat.StreamConfigurationMapCompat
+import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
+import androidx.camera.camera2.pipe.integration.compat.workaround.OutputSizesCorrector
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
 import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera.RunningUseCasesChangeListener
 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraControl
@@ -29,6 +32,7 @@
 import androidx.camera.camera2.pipe.integration.testing.FakeCamera2CameraControlCompat
 import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
 import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraComponentBuilder
+import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.Preview
 import androidx.camera.core.UseCase
@@ -276,6 +280,10 @@
         ),
         cameraStateAdapter = CameraStateAdapter(),
         cameraGraphFlags = CameraGraph.Flags(),
+        cameraQuirks = CameraQuirks(
+            FakeCameraMetadata(),
+            StreamConfigurationMapCompat(null, OutputSizesCorrector(FakeCameraMetadata(), null))
+        ),
         displayInfoManager = DisplayInfoManager(ApplicationProvider.getApplicationContext()),
     ).also {
         useCaseManagerList.add(it)
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
index 5c3279f..ca33199 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
@@ -26,10 +26,14 @@
 import androidx.camera.camera2.pipe.Result3A
 import androidx.camera.camera2.pipe.StreamId
 import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
+import androidx.camera.camera2.pipe.integration.compat.StreamConfigurationMapCompat
+import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
+import androidx.camera.camera2.pipe.integration.compat.workaround.OutputSizesCorrector
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraComponent
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraConfig
 import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera
 import androidx.camera.camera2.pipe.integration.impl.UseCaseCameraRequestControl
+import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
 import androidx.camera.core.UseCase
 import androidx.camera.core.impl.CaptureConfig
 import androidx.camera.core.impl.Config
@@ -40,8 +44,12 @@
 import kotlinx.coroutines.withTimeoutOrNull
 
 class FakeUseCaseCameraComponentBuilder : UseCaseCameraComponent.Builder {
+    private val cameraQuirks = CameraQuirks(
+        FakeCameraMetadata(),
+        StreamConfigurationMapCompat(null, OutputSizesCorrector(FakeCameraMetadata(), null))
+    )
     private var config: UseCaseCameraConfig =
-        UseCaseCameraConfig(emptyList(), CameraStateAdapter(), CameraGraph.Flags())
+        UseCaseCameraConfig(emptyList(), CameraStateAdapter(), cameraQuirks, CameraGraph.Flags())
 
     override fun config(config: UseCaseCameraConfig): UseCaseCameraComponent.Builder {
         this.config = config
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
index 7e5ce4b..ee57224 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
@@ -153,7 +153,30 @@
          */
         val quirkWaitForRepeatingRequestOnDisconnect: Boolean? = null,
 
+        /**
+         * A quirk that finalizes [androidx.camera.camera2.pipe.compat.CaptureSessionState] when
+         * the CameraGraph is stopped or closed. When a CameraGraph is started, the app might
+         * wait for the Surfaces to be released before setting the new Surfaces. This creates a
+         * potential deadlock, and this quirk is aimed to mitigate such behavior by releasing the
+         * Surfaces (finalizing the session) when the graph is stopped or closed.
+         *
+         * - Bug(s): b/277310425
+         * - Device(s): All (but behaviors might differ across devices)
+         * - API levels: All
+         */
         val quirkFinalizeSessionOnCloseBehavior: FinalizeSessionOnCloseBehavior = OFF,
+
+        /**
+         * A quirk that closes the camera capture session when the CameraGraph is stopped or closed.
+         * This is needed in cases where the app that do not wish to receive further frames, or
+         * in cases where not closing the capture session before closing the camera device might
+         * cause the camera close call itself to hang indefinitely.
+         *
+         * - Bug(s): b/277310425, b/277310425
+         * - Device(s): Depends on the situation and the use case.
+         * - API levels: All
+         */
+        val quirkCloseCaptureSessionOnDisconnect: Boolean = false,
     ) {
 
         @JvmInline
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
index 35995c4..3d4ea8d 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
@@ -101,7 +101,7 @@
             captureSequenceProcessorFactory,
             cameraSurfaceManager,
             timeSource,
-            config.flags.quirkFinalizeSessionOnCloseBehavior,
+            config.flags,
             scope
         )
         currentSession = session
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt
index 0852ebf..7a07920 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt
@@ -22,6 +22,7 @@
 import android.view.Surface
 import androidx.annotation.GuardedBy
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraph.Flags.FinalizeSessionOnCloseBehavior
 import androidx.camera.camera2.pipe.CameraSurfaceManager
 import androidx.camera.camera2.pipe.StreamId
@@ -65,7 +66,7 @@
     private val captureSequenceProcessorFactory: Camera2CaptureSequenceProcessorFactory,
     private val cameraSurfaceManager: CameraSurfaceManager,
     private val timeSource: TimeSource,
-    private val finalizeSessionOnCloseBehavior: FinalizeSessionOnCloseBehavior,
+    private val cameraGraphFlags: CameraGraph.Flags,
     private val scope: CoroutineScope
 ) : CameraCaptureSessionWrapper.StateCallback {
     private val debugId = captureSessionDebugIds.incrementAndGet()
@@ -270,7 +271,7 @@
         val graphProcessor = configuredCaptureSession?.processor
         if (graphProcessor != null) {
             // WARNING:
-            // This does NOT call close on the captureSession to avoid potentially slow
+            // This normally does NOT call close on the captureSession to avoid potentially slow
             // reconfiguration during mode switch and shutdown. This avoids unintentional restarts
             // by clearing the internal captureSession variable, clearing all repeating requests,
             // and by aborting any pending single requests.
@@ -294,6 +295,23 @@
                 Debug.traceStop()
             }
 
+            // There are rare, extraordinary circumstances where we might need to close the capture
+            // session. It is possible the app might explicitly wait for the captures to be
+            // completely stopped through signals from CameraSurfaceManager, and in which case
+            // closing the capture session would eventually release the Surfaces [1]. Additionally,
+            // on certain devices, we need to close the capture session, or else the camera device
+            // close call might stall indefinitely [2].
+            //
+            // [1] b/277310425
+            // [2] b/277675483
+            if (cameraGraphFlags.quirkCloseCaptureSessionOnDisconnect) {
+                val captureSession = configuredCaptureSession?.session
+                checkNotNull(captureSession)
+                Debug.trace("$this CameraCaptureSessionWrapper#close") {
+                    Log.debug { "Closing capture session for $this" }
+                    captureSession.close()
+                }
+            }
             Debug.traceStop()
         }
 
@@ -306,15 +324,17 @@
             if (state != State.CLOSED) {
                 if (_cameraDevice == null || !hasAttemptedCaptureSession) {
                     shouldFinalizeSession = true
-                } else if (finalizeSessionOnCloseBehavior ==
-                    FinalizeSessionOnCloseBehavior.IMMEDIATE
-                ) {
-                    shouldFinalizeSession = true
-                } else if (finalizeSessionOnCloseBehavior ==
-                    FinalizeSessionOnCloseBehavior.TIMEOUT
-                ) {
-                    shouldFinalizeSession = true
-                    finalizeSessionDelayMs = 2000L
+                } else {
+                    when (cameraGraphFlags.quirkFinalizeSessionOnCloseBehavior) {
+                        FinalizeSessionOnCloseBehavior.IMMEDIATE -> {
+                            shouldFinalizeSession = true
+                        }
+
+                        FinalizeSessionOnCloseBehavior.TIMEOUT -> {
+                            shouldFinalizeSession = true
+                            finalizeSessionDelayMs = 2000L
+                        }
+                    }
                 }
             }
             _cameraDevice = null
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
index 3635a7c..1236721 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
@@ -23,6 +23,7 @@
 import android.util.Size
 import android.view.Surface
 import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraGraph.Flags.FinalizeSessionOnCloseBehavior
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraMetadata
 import androidx.camera.camera2.pipe.CameraPipe
@@ -128,7 +129,10 @@
                     },
                     CameraSurfaceManager(),
                     SystemTimeSource(),
-                    CameraGraph.Flags.FinalizeSessionOnCloseBehavior.OFF,
+                    CameraGraph.Flags(
+                        quirkFinalizeSessionOnCloseBehavior = FinalizeSessionOnCloseBehavior.OFF,
+                        quirkCloseCaptureSessionOnDisconnect = false,
+                    ),
                     this
                 )
             )
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionStateTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionStateTest.kt
index 45f4731..eafc0ae 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionStateTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionStateTest.kt
@@ -19,6 +19,7 @@
 import android.graphics.SurfaceTexture
 import android.os.Build
 import android.view.Surface
+import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraph.Flags.FinalizeSessionOnCloseBehavior
 import androidx.camera.camera2.pipe.CameraSurfaceManager
 import androidx.camera.camera2.pipe.CaptureSequenceProcessor
@@ -61,6 +62,10 @@
             ): CaptureSequenceProcessor<Request, FakeCaptureSequence> = fakeCaptureSequenceProcessor
         }
     private val timeSource = SystemTimeSource()
+    private val cameraGraphFlags = CameraGraph.Flags(
+        quirkFinalizeSessionOnCloseBehavior = FinalizeSessionOnCloseBehavior.OFF,
+        quirkCloseCaptureSessionOnDisconnect = false,
+    )
 
     private val surface1: Surface = Surface(SurfaceTexture(1))
     private val surface2: Surface = Surface(SurfaceTexture(2))
@@ -91,7 +96,7 @@
                 captureSequenceProcessorFactory,
                 cameraSurfaceManager,
                 timeSource,
-                FinalizeSessionOnCloseBehavior.OFF,
+                cameraGraphFlags,
                 this
             )
         // When disconnect is called first
@@ -114,7 +119,7 @@
                 captureSequenceProcessorFactory,
                 cameraSurfaceManager,
                 timeSource,
-                FinalizeSessionOnCloseBehavior.OFF,
+                cameraGraphFlags,
                 this
             )
 
@@ -142,7 +147,7 @@
                 captureSequenceProcessorFactory,
                 cameraSurfaceManager,
                 timeSource,
-                FinalizeSessionOnCloseBehavior.OFF,
+                cameraGraphFlags,
                 this
             )
 
@@ -176,7 +181,7 @@
                 captureSequenceProcessorFactory,
                 cameraSurfaceManager,
                 timeSource,
-                FinalizeSessionOnCloseBehavior.OFF,
+                cameraGraphFlags,
                 this
             )
         // When surfaces are configured
@@ -200,7 +205,7 @@
                 captureSequenceProcessorFactory,
                 cameraSurfaceManager,
                 timeSource,
-                FinalizeSessionOnCloseBehavior.OFF,
+                cameraGraphFlags,
                 this
             )
         // When surfaces are configured
@@ -224,7 +229,7 @@
                 captureSequenceProcessorFactory,
                 cameraSurfaceManager,
                 timeSource,
-                FinalizeSessionOnCloseBehavior.OFF,
+                cameraGraphFlags,
                 this
             )
         // When surfaces are configured
@@ -238,4 +243,41 @@
         verify(fakeSurfaceListener, times(1)).onSurfaceInactive(eq(surface1))
         verify(fakeSurfaceListener, times(1)).onSurfaceInactive(eq(surface2))
     }
+
+    @Test
+    fun captureSessionStateClosesCaptureSessionWhenQuirkIsEnabled() = runTest {
+        val state =
+            CaptureSessionState(
+                fakeGraphListener,
+                captureSessionFactory,
+                captureSequenceProcessorFactory,
+                cameraSurfaceManager,
+                timeSource,
+                CameraGraph.Flags(
+                    quirkCloseCaptureSessionOnDisconnect = true,
+                ),
+                this
+            )
+
+        // When surfaces are configured
+        state.configureSurfaceMap(mapOf(stream1 to surface1, stream2 to surface2))
+        verify(fakeSurfaceListener, times(1)).onSurfaceActive(eq(surface1))
+        verify(fakeSurfaceListener, times(1)).onSurfaceActive(eq(surface2))
+
+        // And a device is set
+        state.cameraDevice = fakeCameraDevice
+
+        // Advance to make sure a capture session is created.
+        advanceUntilIdle()
+
+        // Feed a fake capture session
+        state.onConfigured(fakeCaptureSession)
+
+        // And the state is then disconnected
+        state.disconnect()
+
+        // Then make sure we do close the capture session.
+        advanceUntilIdle()
+        verify(fakeCaptureSession, times(1)).close()
+    }
 }
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplDeviceTest.java
index c54cc1a..2f3e542 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplDeviceTest.java
@@ -57,6 +57,8 @@
 import androidx.camera.camera2.Camera2Config;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
 import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
+import androidx.camera.camera2.internal.compat.quirk.CameraQuirks;
+import androidx.camera.camera2.internal.compat.workaround.AutoFlashAEModeDisabler;
 import androidx.camera.core.CameraControl;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraXConfig;
@@ -68,6 +70,7 @@
 import androidx.camera.core.impl.CameraCaptureResult;
 import androidx.camera.core.impl.CameraControlInternal;
 import androidx.camera.core.impl.CaptureConfig;
+import androidx.camera.core.impl.Quirks;
 import androidx.camera.core.impl.SessionConfig;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.internal.CameraUseCaseAdapter;
@@ -125,6 +128,7 @@
     private boolean mHasFlashUnit;
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
     private CameraUseCaseAdapter mCamera;
+    private Quirks mCameraQuirks;
 
     @Before
     public void setUp() throws InterruptedException {
@@ -151,6 +155,7 @@
                 mCameraCharacteristics, cameraId);
         mCamera2CameraControlImpl = new Camera2CameraControlImpl(mCameraCharacteristicsCompat,
                 executorService, executorService, mControlUpdateCallback);
+        mCameraQuirks = CameraQuirks.get(cameraId, mCameraCharacteristicsCompat);
 
         mCamera2CameraControlImpl.incrementUseCount();
         mCamera2CameraControlImpl.setActive(true);
@@ -724,9 +729,12 @@
     }
 
     private void assertAeMode(Camera2ImplConfig config, int aeMode) {
-        if (isAeModeSupported(aeMode)) {
+        AutoFlashAEModeDisabler aeModeCorrector = new AutoFlashAEModeDisabler(mCameraQuirks);
+        int aeModeCorrected = aeModeCorrector.getCorrectedAeMode(aeMode);
+
+        if (isAeModeSupported(aeModeCorrected)) {
             assertThat(config.getCaptureRequestOption(
-                    CaptureRequest.CONTROL_AE_MODE, null)).isEqualTo(aeMode);
+                    CaptureRequest.CONTROL_AE_MODE, null)).isEqualTo(aeModeCorrected);
         } else {
             int fallbackMode;
             if (isAeModeSupported(CONTROL_AE_MODE_ON)) {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
index fdd7bae..1f1834bf 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
@@ -16,6 +16,14 @@
 
 package androidx.camera.camera2.internal;
 
+import static android.hardware.DataSpace.STANDARD_BT2020;
+import static android.hardware.DataSpace.TRANSFER_GAMMA2_2;
+import static android.hardware.DataSpace.TRANSFER_GAMMA2_6;
+import static android.hardware.DataSpace.TRANSFER_GAMMA2_8;
+import static android.hardware.DataSpace.TRANSFER_HLG;
+import static android.hardware.DataSpace.TRANSFER_SMPTE_170M;
+import static android.hardware.DataSpace.TRANSFER_SRGB;
+import static android.hardware.DataSpace.TRANSFER_UNSPECIFIED;
 import static android.os.Build.VERSION.SDK_INT;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -118,8 +126,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
@@ -144,6 +154,20 @@
     private static final DynamicRange DYNAMIC_RANGE_HLG10 =
             new DynamicRange(DynamicRange.FORMAT_HLG, DynamicRange.BIT_DEPTH_10_BIT);
 
+    // Enumerate possible SDR transfer functions. This may need to be updated if more transfer
+    // functions are added to the DataSpace class.
+    // This set is notably missing the HLG and PQ transfer functions, though HLG could
+    // technically be used with 8-bit for SDR.
+    // We also exclude LINEAR as most devices should at least apply gamma for SDR.
+    private static final HashSet<Integer> POSSIBLE_COLOR_STANDARDS_SDR =
+            new HashSet<>(Arrays.asList(
+                    TRANSFER_UNSPECIFIED, // Some devices may use this as a default for SDR
+                    TRANSFER_GAMMA2_2,
+                    TRANSFER_GAMMA2_6,
+                    TRANSFER_GAMMA2_8,
+                    TRANSFER_SMPTE_170M,
+                    TRANSFER_SRGB));
+
     /** Thread for all asynchronous calls. */
     private static HandlerThread sHandlerThread;
     /** Handler for all asynchronous calls. */
@@ -348,8 +372,9 @@
             throws ExecutionException, InterruptedException, TimeoutException {
         openCaptureSessionAndVerifyDynamicRangeApplied(
                 /*inputDynamicRange=*/null, // Should default to SDR
-                DataSpace.STANDARD_BT709,
-                DataSpace.TRANSFER_SRGB);
+                /*possibleColorStandards=*/null, // Do not check ColorSpace for SDR; could be many.
+                POSSIBLE_COLOR_STANDARDS_SDR
+        );
     }
 
     @SdkSuppress(minSdkVersion = 33) // HLG dynamic range only supported since API 33
@@ -358,8 +383,8 @@
             throws ExecutionException, InterruptedException, TimeoutException {
         openCaptureSessionAndVerifyDynamicRangeApplied(
                 DYNAMIC_RANGE_HLG10,
-                DataSpace.STANDARD_BT2020,
-                DataSpace.TRANSFER_HLG);
+                Collections.singleton(STANDARD_BT2020),
+                Collections.singleton(TRANSFER_HLG));
     }
 
     // Sharing surface of YUV format is supported since API 28
@@ -1557,8 +1582,8 @@
     @RequiresApi(33) // SurfaceTexture.getDataSpace() was added in API 33
     private void openCaptureSessionAndVerifyDynamicRangeApplied(
             @Nullable DynamicRange inputDynamicRange,
-            int expectedColorStandard,
-            int expectedTransferFn)
+            @Nullable Set<Integer> possibleColorStandards,
+            @Nullable Set<Integer> possibleTransferFns)
             throws ExecutionException, InterruptedException, TimeoutException {
         // 1. Arrange
         if (inputDynamicRange != null) {
@@ -1567,9 +1592,6 @@
                     mDynamicRangesCompat.getSupportedDynamicRanges().contains(inputDynamicRange));
         }
 
-        assumeFalse("Cuttlefish does not set the data space correctly for camera targets.",
-                Build.MODEL.contains("Cuttlefish"));
-
         CountDownLatch latch0 = new CountDownLatch(1);
         AtomicInteger dataSpace = new AtomicInteger(DataSpace.DATASPACE_UNKNOWN);
         ListenableFuture<SurfaceTextureProvider.SurfaceTextureHolder> surfaceTextureHolderFuture =
@@ -1638,12 +1660,16 @@
                 .isTrue();
 
         // Ensure the dataspace matches what is expected
-        assertThat(DataSpace.getStandard(dataSpace.get())).isEqualTo(expectedColorStandard);
-        assertThat(DataSpace.getTransfer(dataSpace.get())).isEqualTo(expectedTransferFn);
+        if (possibleColorStandards != null) {
+            assertThat(DataSpace.getStandard(dataSpace.get())).isIn(possibleColorStandards);
+        }
+        if (possibleTransferFns != null) {
+            assertThat(DataSpace.getTransfer(dataSpace.get())).isIn(possibleTransferFns);
+        }
     }
 
     /**
-     * A implementation to test {@link CameraEventCallback} on CaptureSession.
+     * A implementation to test {@link CameraEventCallback} on CaptureSession.f
      */
     private static class TestCameraEventCallback extends CameraEventCallback {
 
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 066b3c9..1612a15 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -37,7 +37,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
 import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.camera2.internal.annotation.CameraExecutor;
 import androidx.camera.camera2.internal.compat.ApiCompat;
@@ -679,7 +678,7 @@
      * block until completion.
      *
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     boolean isUseCaseAttached(@NonNull UseCase useCase) {
         try {
             String useCaseId = getUseCaseId(useCase);
@@ -1031,7 +1030,7 @@
     }
 
     @NonNull
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     public CameraAvailability getCameraAvailability() {
         return mCameraAvailability;
     }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
index 14a7558..95dda70 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
@@ -427,17 +427,21 @@
 
         long dynamicRangeProfile = DynamicRangeProfiles.STANDARD;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-            DynamicRange requestedDynamicRange = outputConfig.getDynamicRange();
-            Long dynamicRangeProfileOrNull =
-                    DynamicRangeConversions.dynamicRangeToFirstSupportedProfile(
-                            outputConfig.getDynamicRange(),
-                            mDynamicRangesCompat.toDynamicRangeProfiles());
-            if (dynamicRangeProfileOrNull == null) {
-                Logger.e(TAG, "Requested dynamic range is not supported. Defaulting to STANDARD "
-                        + "dynamic range profile.\nRequested dynamic range:\n  "
-                        + requestedDynamicRange);
-            } else {
-                dynamicRangeProfile = dynamicRangeProfileOrNull;
+            DynamicRangeProfiles dynamicRangeProfiles =
+                    mDynamicRangesCompat.toDynamicRangeProfiles();
+            if (dynamicRangeProfiles != null) {
+                DynamicRange requestedDynamicRange = outputConfig.getDynamicRange();
+                Long dynamicRangeProfileOrNull =
+                        DynamicRangeConversions.dynamicRangeToFirstSupportedProfile(
+                                requestedDynamicRange, dynamicRangeProfiles);
+                if (dynamicRangeProfileOrNull == null) {
+                    Logger.e(TAG,
+                            "Requested dynamic range is not supported. Defaulting to STANDARD "
+                                    + "dynamic range profile.\nRequested dynamic range:\n  "
+                                    + requestedDynamicRange);
+                } else {
+                    dynamicRangeProfile = dynamicRangeProfileOrNull;
+                }
             }
         }
         outputConfiguration.setDynamicRangeProfile(dynamicRangeProfile);
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompat.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompat.java
index 0ab747c..1ca1a561 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompat.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompat.java
@@ -29,7 +29,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RequiresPermission;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.impl.utils.MainThreadAsyncHandler;
 
 import java.util.Map;
@@ -77,7 +77,7 @@
      * Get a {@link CameraManagerCompat} instance from a provided {@link CameraManagerCompatImpl}.
      *
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public static CameraManagerCompat from(@NonNull final CameraManagerCompatImpl impl) {
         return new CameraManagerCompat(impl);
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java
index e7d3d64..0af3554 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java
@@ -119,7 +119,7 @@
      * Creates an instance from a framework android.hardware.camera2.params.DynamicRangeProfiles
      * object.
      *
-     * @param dynamicRangeProfiles a {@link android.hardware.camera2.params.DynamicRangeProfiles).
+     * @param dynamicRangeProfiles a {@link android.hardware.camera2.params.DynamicRangeProfiles}.
      * @return an equivalent {@link DynamicRangesCompat} object.
      */
     @Nullable
@@ -138,16 +138,17 @@
 
     /**
      * Returns the underlying framework
-     * {@link android.hardware.camera2.params.DynamicRangeProfiles).
+     * {@link android.hardware.camera2.params.DynamicRangeProfiles}.
      *
-     * @return the underlying {@link android.hardware.camera2.params.DynamicRangeProfiles).
+     * @return the underlying {@link android.hardware.camera2.params.DynamicRangeProfiles} or
+     * {@code null} if the device doesn't support 10 bit dynamic range.
      */
-    @NonNull
+    @Nullable
     @RequiresApi(33)
     public DynamicRangeProfiles toDynamicRangeProfiles() {
         Preconditions.checkState(Build.VERSION.SDK_INT >= 33, "DynamicRangesCompat can only be "
                 + "converted to DynamicRangeProfiles on API 33 or higher.");
-        return Preconditions.checkNotNull(mImpl.unwrap());
+        return mImpl.unwrap();
     }
 
     interface DynamicRangeProfilesCompatImpl {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java
index 5c0a513..ba916eb 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java
@@ -30,17 +30,18 @@
  * Quirk denoting the video profile list returns by {@link EncoderProfiles} is invalid.
  *
  * <p>QuirkSummary
- *     Bug Id: 267727595
+ *     Bug Id: 267727595, 278860860
  *     Description: When using {@link EncoderProfiles} on TP1A or TD1A builds of Android API 33,
  *                  {@link EncoderProfiles#getVideoProfiles()} returns a list with size one, but
  *                  the single value in the list is null. This is not the expected behavior, and
  *                  makes {@link EncoderProfiles} lack of video information.
- *     Device(s): Pixel 4 and above pixel devices with TP1A or TD1A builds (API 33).
+ *     Device(s): Pixel 4 and above pixel devices with TP1A or TD1A builds (API 33), Samsung devices
+ *                with TP1A build (API 33).
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class InvalidVideoProfilesQuirk implements Quirk {
 
-    static final List<String> AFFECTED_MODELS = Arrays.asList(
+    static final List<String> AFFECTED_PIXEL_MODELS = Arrays.asList(
             "pixel 4",
             "pixel 4a",
             "pixel 4a (5g)",
@@ -55,22 +56,30 @@
     );
 
     static boolean load() {
-        return isAffectedModel() && isAffectedBuild();
+        return isAffectedSamsungDevices() || isAffectedPixelDevices();
     }
 
-    private static boolean isAffectedModel() {
-        return AFFECTED_MODELS.contains(Build.MODEL.toLowerCase(Locale.US));
+    private static boolean isAffectedSamsungDevices() {
+        return "samsung".equalsIgnoreCase(Build.BRAND) && isTp1aBuild();
     }
 
-    private static boolean isAffectedBuild() {
+    private static boolean isAffectedPixelDevices() {
+        return isAffectedPixelModel() && isAffectedPixelBuild();
+    }
+
+    private static boolean isAffectedPixelModel() {
+        return AFFECTED_PIXEL_MODELS.contains(Build.MODEL.toLowerCase(Locale.ROOT));
+    }
+
+    private static boolean isAffectedPixelBuild() {
         return isTp1aBuild() || isTd1aBuild();
     }
 
     private static boolean isTp1aBuild() {
-        return Build.ID.startsWith("TP1A");
+        return Build.ID.toLowerCase(Locale.ROOT).startsWith("tp1a");
     }
 
     private static boolean isTd1aBuild() {
-        return Build.ID.startsWith("TD1A");
+        return Build.ID.toLowerCase(Locale.ROOT).startsWith("td1a");
     }
 }
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt
index 76fdf54..56d280e 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt
@@ -177,6 +177,16 @@
 
     @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
     @Test
+    fun producesNullDynamicRangeProfilesFromNullCharacteristics() {
+        val characteristics = newCameraCharacteristicsCompat()
+
+        val dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(characteristics)
+
+        assertThat(dynamicRangesCompat.toDynamicRangeProfiles()).isNull()
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
     fun canProduceDynamicRangesCompatFromCharacteristics() {
         val characteristics = newCameraCharacteristicsCompat()
         Shadow.extract<ShadowCameraCharacteristics>(
diff --git a/camera/camera-core/api/current.txt b/camera/camera-core/api/current.txt
index 20658d2..2286727 100644
--- a/camera/camera-core/api/current.txt
+++ b/camera/camera-core/api/current.txt
@@ -213,7 +213,7 @@
     method public boolean isOutputImageRotationEnabled();
     method public void setAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     field public static final int COORDINATE_SYSTEM_ORIGINAL = 0; // 0x0
     field public static final int OUTPUT_IMAGE_FORMAT_RGBA_8888 = 2; // 0x2
     field public static final int OUTPUT_IMAGE_FORMAT_YUV_420_888 = 1; // 0x1
@@ -253,7 +253,7 @@
     method public void setCropAspectRatio(android.util.Rational);
     method public void setFlashMode(int);
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     method public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
     method public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
     field public static final int CAPTURE_MODE_MAXIMIZE_QUALITY = 0; // 0x0
@@ -474,6 +474,7 @@
   }
 
   @RequiresApi(21) public abstract class UseCase {
+    method public static int snapToSurfaceRotation(@IntRange(from=0, to=359) int);
   }
 
   @RequiresApi(21) public final class UseCaseGroup {
diff --git a/camera/camera-core/api/public_plus_experimental_current.txt b/camera/camera-core/api/public_plus_experimental_current.txt
index 635067b..ee3714c 100644
--- a/camera/camera-core/api/public_plus_experimental_current.txt
+++ b/camera/camera-core/api/public_plus_experimental_current.txt
@@ -228,7 +228,7 @@
     method public boolean isOutputImageRotationEnabled();
     method public void setAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     field public static final int COORDINATE_SYSTEM_ORIGINAL = 0; // 0x0
     field public static final int OUTPUT_IMAGE_FORMAT_RGBA_8888 = 2; // 0x2
     field public static final int OUTPUT_IMAGE_FORMAT_YUV_420_888 = 1; // 0x1
@@ -268,7 +268,7 @@
     method public void setCropAspectRatio(android.util.Rational);
     method public void setFlashMode(int);
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     method public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
     method public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
     field public static final int CAPTURE_MODE_MAXIMIZE_QUALITY = 0; // 0x0
@@ -491,6 +491,7 @@
   }
 
   @RequiresApi(21) public abstract class UseCase {
+    method public static int snapToSurfaceRotation(@IntRange(from=0, to=359) int);
   }
 
   @RequiresApi(21) public final class UseCaseGroup {
diff --git a/camera/camera-core/api/restricted_current.txt b/camera/camera-core/api/restricted_current.txt
index 20658d2..2286727 100644
--- a/camera/camera-core/api/restricted_current.txt
+++ b/camera/camera-core/api/restricted_current.txt
@@ -213,7 +213,7 @@
     method public boolean isOutputImageRotationEnabled();
     method public void setAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     field public static final int COORDINATE_SYSTEM_ORIGINAL = 0; // 0x0
     field public static final int OUTPUT_IMAGE_FORMAT_RGBA_8888 = 2; // 0x2
     field public static final int OUTPUT_IMAGE_FORMAT_YUV_420_888 = 1; // 0x1
@@ -253,7 +253,7 @@
     method public void setCropAspectRatio(android.util.Rational);
     method public void setFlashMode(int);
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     method public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
     method public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
     field public static final int CAPTURE_MODE_MAXIMIZE_QUALITY = 0; // 0x0
@@ -474,6 +474,7 @@
   }
 
   @RequiresApi(21) public abstract class UseCase {
+    method public static int snapToSurfaceRotation(@IntRange(from=0, to=359) int);
   }
 
   @RequiresApi(21) public final class UseCaseGroup {
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt
index 71f4651..52cb1a2 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt
@@ -25,6 +25,7 @@
 import androidx.camera.core.MirrorMode.MIRROR_MODE_OFF
 import androidx.camera.core.MirrorMode.MIRROR_MODE_ON
 import androidx.camera.core.MirrorMode.MIRROR_MODE_ON_FRONT_ONLY
+import androidx.camera.core.UseCase.snapToSurfaceRotation
 import androidx.camera.core.concurrent.CameraCoordinator
 import androidx.camera.core.impl.Config
 import androidx.camera.core.impl.ImageOutputConfig
@@ -42,6 +43,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
+import androidx.testutils.assertThrows
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
@@ -292,6 +294,24 @@
         assertThat(fakeUseCase.isMirroringRequired(fakeFrontCamera)).isTrue()
     }
 
+    @Test
+    fun snapToSurfaceRotation_toCorrectValue() {
+        assertThat(snapToSurfaceRotation(45)).isEqualTo(Surface.ROTATION_270)
+        assertThat(snapToSurfaceRotation(135)).isEqualTo(Surface.ROTATION_180)
+        assertThat(snapToSurfaceRotation(225)).isEqualTo(Surface.ROTATION_90)
+        assertThat(snapToSurfaceRotation(315)).isEqualTo(Surface.ROTATION_0)
+    }
+
+    @Test
+    fun snapToSurfaceRotation_invalidInput() {
+        assertThrows<IllegalArgumentException> {
+            snapToSurfaceRotation(-1)
+        }
+        assertThrows<IllegalArgumentException> {
+            snapToSurfaceRotation(360)
+        }
+    }
+
     private fun createFakeUseCase(
         targetRotation: Int = Surface.ROTATION_0,
         mirrorMode: Int? = null,
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt
index 099b42b..0d7695d8e 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt
@@ -37,14 +37,15 @@
 import com.google.common.truth.Truth.assertThat
 import java.util.Locale
 import kotlin.coroutines.ContinuationInterceptor
-import kotlin.coroutines.resume
+import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.android.asCoroutineDispatcher
 import kotlinx.coroutines.currentCoroutineContext
 import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withContext
+import kotlinx.coroutines.withTimeoutOrNull
 import org.junit.After
+import org.junit.Assert.fail
 import org.junit.Before
 import org.junit.BeforeClass
 import org.junit.Rule
@@ -147,18 +148,22 @@
         val inputSurface = Surface(surfaceTexture).apply {
             surfacesToRelease.add(this)
         }
-        // Create Bitmap for drawing
-        val inputImage = createBitmap(WIDTH, HEIGHT)
+        // Listen for OnFrameAvailable updates before drawing.
+        val deferredOnFrameAvailable = CompletableDeferred<Unit>()
+        surfaceTexture.setOnFrameAvailableListener({
+            deferredOnFrameAvailable.complete(Unit)
+        }, Handler(Looper.getMainLooper()))
+
         // Draw bitmap to inputSurface.
+        val inputImage = createBitmap(WIDTH, HEIGHT)
         val canvas = inputSurface.lockHardwareCanvas()
         canvas.drawBitmap(inputImage, 0f, 0f, null)
         inputSurface.unlockCanvasAndPost(canvas)
+
         // Wait for frame available and update texture.
-        suspendCancellableCoroutine { continuation ->
-            surfaceTexture.setOnFrameAvailableListener({
-                continuation.resume(Unit)
-            }, Handler(Looper.getMainLooper()))
-        }
+        withTimeoutOrNull(5_000) {
+            deferredOnFrameAvailable.await()
+        } ?: fail("Timed out waiting for SurfaceTexture frame available.")
         surfaceTexture.updateTexImage()
 
         // Act: take a snapshot.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index c708353..1c9e38a 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -41,6 +41,7 @@
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_TARGET_NAME;
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_USE_CASE_EVENT_CALLBACK;
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_ZSL_DISABLED;
+import static androidx.camera.core.impl.utils.TransformUtils.within360;
 import static androidx.camera.core.internal.ThreadConfig.OPTION_BACKGROUND_EXECUTOR;
 
 import android.graphics.ImageFormat;
@@ -441,8 +442,7 @@
      * <p>
      * The rotation can be set when constructing an {@link ImageAnalysis} instance using
      * {@link ImageAnalysis.Builder#setTargetRotation(int)}, or dynamically by calling
-     * {@link ImageAnalysis#setTargetRotation(int)} or
-     * {@link ImageAnalysis#setTargetRotationDegrees(int)}. If not set, the target rotation
+     * {@link ImageAnalysis#setTargetRotation(int)}. If not set, the target rotation
      * defaults to the value of {@link Display#getRotation()} of the default display at the time
      * the use case is created. The use case is fully created once it has been attached to a camera.
      * </p>
@@ -471,10 +471,11 @@
      * set the target rotation.  This way, the rotation output to the Analyzer will indicate
      * which way is down for a given image.  This is important since display orientation may be
      * locked by device default, user setting, or app configuration, and some devices may not
-     * transition to a reverse-portrait display orientation.  In these cases, use
-     * {@link ImageAnalysis#setTargetRotationDegrees(int)} to set target rotation dynamically
-     * according to the {@link android.view.OrientationEventListener}, without re-creating the
-     * use case. See {@link #setTargetRotationDegrees} for more information.
+     * transition to a reverse-portrait display orientation. In these cases, set target rotation
+     * dynamically according to the {@link android.view.OrientationEventListener}, without
+     * re-creating the use case. {@link UseCase#snapToSurfaceRotation(int)} is a helper function to
+     * convert the orientation of the {@link android.view.OrientationEventListener} to a rotation
+     * value. See {@link UseCase#snapToSurfaceRotation(int)} for more information and sample code.
      *
      * <p>When this function is called, value set by
      * {@link ImageAnalysis.Builder#setTargetResolution(Size)} will be updated automatically to
@@ -497,6 +498,7 @@
         }
     }
 
+    // TODO(b/277999375): Remove API setTargetRotationDegrees.
     /**
      * Sets the target rotation in degrees.
      *
@@ -560,9 +562,12 @@
      * @param degrees Desired rotation degree of the output image.
      * @see #setTargetRotation(int)
      * @see #getTargetRotation()
+     * @deprecated Use {@link UseCase#snapToSurfaceRotation(int)} and
+     * {@link #setTargetRotation(int)} to convert and set the rotation.
      */
+    @Deprecated // TODO(b/277999375): Remove API setTargetRotationDegrees.
     public void setTargetRotationDegrees(int degrees) {
-        setTargetRotation(orientationDegreesToSurfaceRotation(degrees));
+        setTargetRotation(snapToSurfaceRotation(within360(degrees)));
     }
 
     /**
@@ -1315,9 +1320,8 @@
          * Rotation values are relative to the "natural" rotation, {@link Surface#ROTATION_0}.
          *
          * <p>In general, it is best to additionally set the target rotation dynamically on the use
-         * case.  See
-         * {@link androidx.camera.core.ImageAnalysis#setTargetRotationDegrees(int)} for additional
-         * documentation.
+         * case. See {@link androidx.camera.core.ImageAnalysis#setTargetRotation(int)} for
+         * additional documentation.
          *
          * <p>If not set, the target rotation will default to the value of
          * {@link android.view.Display#getRotation()} of the default display at the time the
@@ -1326,7 +1330,6 @@
          * @param rotation The rotation of the intended target.
          * @return The current Builder.
          * @see androidx.camera.core.ImageAnalysis#setTargetRotation(int)
-         * @see androidx.camera.core.ImageAnalysis#setTargetRotationDegrees(int)
          * @see android.view.OrientationEventListener
          */
         @NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 27c35c0..4b48ba5 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -46,6 +46,7 @@
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_ZSL_DISABLED;
 import static androidx.camera.core.impl.utils.Threads.checkMainThread;
 import static androidx.camera.core.impl.utils.TransformUtils.is90or270;
+import static androidx.camera.core.impl.utils.TransformUtils.within360;
 import static androidx.camera.core.internal.utils.ImageUtil.computeCropRectFromAspectRatio;
 import static androidx.camera.core.internal.utils.ImageUtil.isAspectRatioValid;
 import static androidx.core.util.Preconditions.checkNotNull;
@@ -700,8 +701,7 @@
      *
      * <p>The rotation can be set prior to constructing an ImageCapture using
      * {@link ImageCapture.Builder#setTargetRotation(int)} or dynamically by calling
-     * {@link ImageCapture#setTargetRotation(int)} or
-     * {@link ImageCapture#setTargetRotationDegrees(int)}. The rotation of an image taken is
+     * {@link ImageCapture#setTargetRotation(int)}. The rotation of an image taken is
      * determined by the rotation value set at the time image capture is initiated, such as when
      * calling {@link #takePicture(Executor, OnImageCapturedCallback)}.
      *
@@ -731,10 +731,11 @@
      * set the target rotation.  This way, the rotation output will indicate which way is down for
      * a given image.  This is important since display orientation may be locked by device
      * default, user setting, or app configuration, and some devices may not transition to a
-     * reverse-portrait display orientation. In these cases,
-     * use {@link #setTargetRotationDegrees} to set target rotation dynamically according to the
-     * {@link android.view.OrientationEventListener}, without re-creating the use case.
-     * See {@link #setTargetRotationDegrees} for more information.
+     * reverse-portrait display orientation. In these cases, set target rotation dynamically
+     * according to the {@link android.view.OrientationEventListener}, without re-creating the
+     * use case. {@link UseCase#snapToSurfaceRotation(int)} is a helper function to convert the
+     * orientation of the {@link android.view.OrientationEventListener} to a rotation value.
+     * See {@link UseCase#snapToSurfaceRotation(int)} for more information and sample code.
      *
      * <p>When this function is called, value set by
      * {@link ImageCapture.Builder#setTargetResolution(Size)} will be updated automatically to make
@@ -843,9 +844,12 @@
      * @param degrees Desired rotation degree of the output image.
      * @see #setTargetRotation(int)
      * @see #getTargetRotation()
+     * @deprecated Use {@link UseCase#snapToSurfaceRotation(int)} and
+     * {@link #setTargetRotation(int)} to convert and set the rotation.
      */
+    @Deprecated // TODO(b/277999375): Remove API setTargetRotationDegrees.
     public void setTargetRotationDegrees(int degrees) {
-        setTargetRotation(orientationDegreesToSurfaceRotation(degrees));
+        setTargetRotation(snapToSurfaceRotation(within360(degrees)));
     }
 
     /**
@@ -1697,11 +1701,6 @@
     private boolean isNodeEnabled() {
         checkMainThread();
         ImageCaptureConfig config = (ImageCaptureConfig) getCurrentConfig();
-        if (config.getImageReaderProxyProvider() != null) {
-            // Use old pipeline for custom ImageReader.
-            return false;
-        }
-
         if (config.getBufferFormat(ImageFormat.JPEG) != ImageFormat.JPEG) {
             // Use old pipeline for non-JPEG output format.
             return false;
@@ -2795,7 +2794,7 @@
          * Rotation values are relative to the "natural" rotation, {@link Surface#ROTATION_0}.
          *
          * <p>In general, it is best to additionally set the target rotation dynamically on the use
-         * case.  See {@link androidx.camera.core.ImageCapture#setTargetRotationDegrees(int)} for
+         * case. See {@link androidx.camera.core.ImageCapture#setTargetRotation(int)} for
          * additional documentation.
          *
          * <p>If not set, the target rotation will default to the value of
@@ -2805,7 +2804,6 @@
          * @param rotation The rotation of the intended target.
          * @return The current Builder.
          * @see androidx.camera.core.ImageCapture#setTargetRotation(int)
-         * @see androidx.camera.core.ImageCapture#setTargetRotationDegrees(int)
          * @see android.view.OrientationEventListener
          */
         @NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index adcb322..0136410 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -26,6 +26,7 @@
 import static androidx.camera.core.impl.utils.TransformUtils.within360;
 import static androidx.camera.core.processing.TargetUtils.isSuperset;
 import static androidx.core.util.Preconditions.checkArgument;
+import static androidx.core.util.Preconditions.checkArgumentInRange;
 
 import android.annotation.SuppressLint;
 import android.graphics.Matrix;
@@ -33,6 +34,7 @@
 import android.media.ImageReader;
 import android.util.Range;
 import android.util.Size;
+import android.view.OrientationEventListener;
 import android.view.Surface;
 
 import androidx.annotation.CallSuper;
@@ -292,17 +294,64 @@
     }
 
     /**
-     * Converts orientation degrees to {@link Surface} rotation.
+     * A utility function that can convert the orientation degrees of
+     * {@link OrientationEventListener} to the nearest {@link Surface} rotation.
+     *
+     * <p>In general, it is best to use an {@link android.view.OrientationEventListener} to set
+     * the UseCase target rotation. This way, the rotation output will indicate which way is down
+     * for a given image or video. This is important since display orientation may be locked by
+     * device default, user setting, or app configuration, and some devices may not transition to a
+     * reverse-portrait display orientation. In these cases, set target rotation dynamically
+     * according to the {@link android.view.OrientationEventListener}, without re-creating the
+     * use case. The sample code is as below:
+     * <pre>{@code
+     * public class CameraXActivity extends AppCompatActivity {
+     *
+     *     private OrientationEventListener mOrientationEventListener;
+     *
+     *     @Override
+     *     protected void onStart() {
+     *         super.onStart();
+     *         if (mOrientationEventListener == null) {
+     *             mOrientationEventListener = new OrientationEventListener(this) {
+     *                 @Override
+     *                 public void onOrientationChanged(int orientation) {
+     *                     if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
+     *                         return;
+     *                     }
+     *                     int rotation = UseCase.snapToSurfaceRotation(orientation);
+     *                     mImageCapture.setTargetRotation(rotation);
+     *                     mImageAnalysis.setTargetRotation(rotation);
+     *                     mVideoCapture.setTargetRotation(rotation);
+     *                 }
+     *             };
+     *         }
+     *         mOrientationEventListener.enable();
+     *     }
+     *
+     *     @Override
+     *     protected void onStop() {
+     *         super.onStop();
+     *         mOrientationEventListener.disable();
+     *     }
+     * }
+     * }</pre>
+     *
+     * @param orientation the orientation degrees in range [0, 359].
+     * @return surface rotation. One of {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
+     * {@link Surface#ROTATION_180} and {@link Surface#ROTATION_270}.
+     * @throws IllegalArgumentException if the input orientation degrees is not in range [0, 359].
+     * @see ImageCapture#setTargetRotation(int)
+     * @see ImageAnalysis#setTargetRotation(int)
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
     @ImageOutputConfig.RotationValue
-    protected static int orientationDegreesToSurfaceRotation(int degrees) {
-        int degreesWithin360 = within360(degrees);
-        if (degreesWithin360 >= 315 || degreesWithin360 < 45) {
+    public static int snapToSurfaceRotation(@IntRange(from = 0, to = 359) int orientation) {
+        checkArgumentInRange(orientation, 0, 359, "orientation");
+        if (orientation >= 315 || orientation < 45) {
             return Surface.ROTATION_0;
-        } else if (degreesWithin360 >= 225) {
+        } else if (orientation >= 225) {
             return Surface.ROTATION_90;
-        } else if (degreesWithin360 >= 135) {
+        } else if (orientation >= 135) {
             return Surface.ROTATION_180;
         } else {
             return Surface.ROTATION_270;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/CaptureNode.java b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/CaptureNode.java
index e0f9eda..a96506f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/CaptureNode.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/CaptureNode.java
@@ -36,6 +36,7 @@
 import androidx.camera.core.ForwardingImageProxy;
 import androidx.camera.core.ImageCaptureException;
 import androidx.camera.core.ImageProxy;
+import androidx.camera.core.ImageReaderProxyProvider;
 import androidx.camera.core.ImageReaderProxys;
 import androidx.camera.core.Logger;
 import androidx.camera.core.MetadataImageReader;
@@ -101,7 +102,15 @@
         Consumer<ProcessingRequest> requestConsumer;
         ImageReaderProxy wrappedImageReader;
         boolean hasMetadata = !inputEdge.isVirtualCamera();
-        if (hasMetadata) {
+        if (inputEdge.getImageReaderProxyProvider() != null) {
+            wrappedImageReader = inputEdge.getImageReaderProxyProvider().newInstance(
+                    size.getWidth(), size.getHeight(), format, MAX_IMAGES, 0);
+            requestConsumer = request -> {
+                // Ignore incoming requests. ImageReaderProxyProvider is only for unit tests. If
+                // we make it public later, we need to also drop the TakePictureRequest in the
+                // TakePictureManager.
+            };
+        } else if (hasMetadata) {
             // Use MetadataImageReader if the input edge expects metadata.
             MetadataImageReader metadataImageReader = new MetadataImageReader(size.getWidth(),
                     size.getHeight(), format, MAX_IMAGES);
@@ -292,6 +301,12 @@
         abstract boolean isVirtualCamera();
 
         /**
+         * Whether the pipeline is connected to a virtual camera.
+         */
+        @Nullable
+        abstract ImageReaderProxyProvider getImageReaderProxyProvider();
+
+        /**
          * Edge that accepts {@link ProcessingRequest}.
          */
         @NonNull
@@ -333,9 +348,10 @@
         }
 
         @NonNull
-        static In of(Size size, int format, boolean isVirtualCamera) {
+        static In of(Size size, int format, boolean isVirtualCamera,
+                @Nullable ImageReaderProxyProvider imageReaderProxyProvider) {
             return new AutoValue_CaptureNode_In(size, format, isVirtualCamera,
-                    new Edge<>(), new Edge<>());
+                    imageReaderProxyProvider, new Edge<>(), new Edge<>());
         }
     }
 
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ImagePipeline.java b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ImagePipeline.java
index 13b05cf..b4f0b28 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ImagePipeline.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ImagePipeline.java
@@ -111,8 +111,11 @@
                 cameraEffect != null ? new InternalImageProcessor(cameraEffect) : null);
 
         // Connect nodes
-        mPipelineIn = CaptureNode.In.of(cameraSurfaceSize, mUseCaseConfig.getInputFormat(),
-                isVirtualCamera);
+        mPipelineIn = CaptureNode.In.of(
+                cameraSurfaceSize,
+                mUseCaseConfig.getInputFormat(),
+                isVirtualCamera,
+                mUseCaseConfig.getImageReaderProxyProvider());
         CaptureNode.Out captureOut = mCaptureNode.transform(mPipelineIn);
         ProcessingNode.In processingIn = mBundlingNode.transform(captureOut);
         mProcessingNode.transform(processingIn);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurface.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurface.java
index 803bfed..58deea49 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurface.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurface.java
@@ -27,6 +27,7 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Logger;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.Futures;
@@ -331,7 +332,7 @@
         return mPrescribedStreamFormat;
     }
 
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public int getUseCount() {
         synchronized (mLock) {
             return mUseCount;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java
index 74389f1..d9c51b0 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java
@@ -34,7 +34,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraEffect;
 import androidx.camera.core.Logger;
@@ -239,7 +238,7 @@
     /**
      * Returns the close state.
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     public boolean isClosed() {
         synchronized (mLock) {
             return mIsClosed;
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
index 682887e..3195cae 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
@@ -163,23 +163,6 @@
     }
 
     @Test
-    public void setTargetRotationDegrees() {
-        ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
-        imageAnalysis.setTargetRotationDegrees(45);
-        assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_270);
-        imageAnalysis.setTargetRotationDegrees(135);
-        assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
-        imageAnalysis.setTargetRotationDegrees(225);
-        assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_90);
-        imageAnalysis.setTargetRotationDegrees(315);
-        assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_0);
-        imageAnalysis.setTargetRotationDegrees(405);
-        assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_270);
-        imageAnalysis.setTargetRotationDegrees(-45);
-        assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_0);
-    }
-
-    @Test
     public void defaultMirrorModeIsOff() {
         ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
         assertThat(imageAnalysis.getMirrorModeInternal()).isEqualTo(MIRROR_MODE_OFF);
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
index 5581da2..8d8aa3e 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
@@ -33,8 +33,8 @@
 import androidx.camera.core.ImageCapture.ImageCaptureRequest
 import androidx.camera.core.ImageCapture.ImageCaptureRequestProcessor
 import androidx.camera.core.ImageCapture.ImageCaptureRequestProcessor.ImageCaptor
-import androidx.camera.core.MirrorMode.MIRROR_MODE_ON_FRONT_ONLY
 import androidx.camera.core.MirrorMode.MIRROR_MODE_OFF
+import androidx.camera.core.MirrorMode.MIRROR_MODE_ON_FRONT_ONLY
 import androidx.camera.core.impl.CameraConfig
 import androidx.camera.core.impl.CameraFactory
 import androidx.camera.core.impl.CaptureConfig
@@ -183,23 +183,6 @@
     }
 
     @Test
-    fun setTargetRotationDegrees() {
-        val imageCapture = ImageCapture.Builder().build()
-        imageCapture.setTargetRotationDegrees(45)
-        assertThat(imageCapture.targetRotation).isEqualTo(Surface.ROTATION_270)
-        imageCapture.setTargetRotationDegrees(135)
-        assertThat(imageCapture.targetRotation).isEqualTo(Surface.ROTATION_180)
-        imageCapture.setTargetRotationDegrees(225)
-        assertThat(imageCapture.targetRotation).isEqualTo(Surface.ROTATION_90)
-        imageCapture.setTargetRotationDegrees(315)
-        assertThat(imageCapture.targetRotation).isEqualTo(Surface.ROTATION_0)
-        imageCapture.setTargetRotationDegrees(405)
-        assertThat(imageCapture.targetRotation).isEqualTo(Surface.ROTATION_270)
-        imageCapture.setTargetRotationDegrees(-45)
-        assertThat(imageCapture.targetRotation).isEqualTo(Surface.ROTATION_0)
-    }
-
-    @Test
     fun defaultMirrorModeIsOff() {
         val imageCapture = ImageCapture.Builder().build()
         assertThat(imageCapture.mirrorModeInternal).isEqualTo(MIRROR_MODE_OFF)
@@ -306,14 +289,14 @@
     }
 
     @Test
-    fun useImageReaderProvider_pipelineDisabled() {
+    fun useImageReaderProvider_pipelineEnabled() {
         assertThat(
             bindImageCapture(
                 useProcessingPipeline = true,
                 bufferFormat = ImageFormat.JPEG,
                 imageReaderProxyProvider = getImageReaderProxyProvider(),
             ).isProcessingPipelineEnabled
-        ).isFalse()
+        ).isTrue()
     }
 
     @Test
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt
index acc1781..bf80cb5 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt
@@ -21,9 +21,11 @@
 import android.os.Looper.getMainLooper
 import android.util.Size
 import androidx.camera.core.ImageProxy
+import androidx.camera.core.ImageReaderProxyProvider
 import androidx.camera.core.imagecapture.Utils.createCaptureBundle
 import androidx.camera.core.imagecapture.Utils.createFakeImage
 import androidx.camera.core.impl.utils.futures.Futures
+import androidx.camera.testing.fakes.FakeImageReaderProxy
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
@@ -52,7 +54,7 @@
 
     @Before
     fun setUp() {
-        captureNodeIn = CaptureNode.In.of(Size(10, 10), ImageFormat.JPEG, false)
+        captureNodeIn = CaptureNode.In.of(Size(10, 10), ImageFormat.JPEG, false, null)
         captureNodeOut = captureNode.transform(captureNodeIn)
         captureNodeOut.imageEdge.setListener {
             imagePropagated.add(it)
@@ -68,6 +70,22 @@
     }
 
     @Test
+    fun hasImageReaderProxyProvider_useTheProvidedImageReader() {
+        // Arrange: create a fake ImageReaderProxyProvider.
+        val imageReader = FakeImageReaderProxy(CaptureNode.MAX_IMAGES)
+        val imageReaderProvider = ImageReaderProxyProvider { _, _, _, _, _ ->
+            imageReader
+        }
+        val input = CaptureNode.In.of(Size(10, 10), ImageFormat.JPEG, false, imageReaderProvider)
+        // Act: transform.
+        val node = CaptureNode()
+        node.transform(input)
+        // Assert: ImageReaderProxyProvider is used.
+        assertThat(input.surface.surface.get()).isEqualTo(imageReader.surface)
+        node.release()
+    }
+
+    @Test
     fun release_imageReaderNotClosedUntilTermination() {
         // Arrange: increment the DeferrableSurface's use count to prevent it from being terminated.
         captureNode.inputEdge.surface.incrementUseCount()
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/ImagePipelineTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/ImagePipelineTest.kt
index de40c35..5b96555 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/ImagePipelineTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/ImagePipelineTest.kt
@@ -28,6 +28,7 @@
 import androidx.camera.core.ImageCapture.CaptureMode
 import androidx.camera.core.ImageCaptureException
 import androidx.camera.core.ImageProxy
+import androidx.camera.core.ImageReaderProxyProvider
 import androidx.camera.core.SafeCloseImageReaderProxy
 import androidx.camera.core.imagecapture.CaptureNode.MAX_IMAGES
 import androidx.camera.core.imagecapture.ImagePipeline.JPEG_QUALITY_MAX_QUALITY
@@ -89,9 +90,10 @@
     @Before
     fun setUp() {
         // Create ImageCaptureConfig.
-        val builder = ImageCapture.Builder().setCaptureOptionUnpacker { _, builder ->
-            builder.templateType = TEMPLATE_TYPE
-        }
+        val builder = ImageCapture.Builder()
+            .setCaptureOptionUnpacker { _, builder ->
+                builder.templateType = TEMPLATE_TYPE
+            }
         builder.mutableConfig.insertOption(OPTION_IO_EXECUTOR, mainThreadExecutor())
         builder.mutableConfig.insertOption(ImageInputConfig.OPTION_INPUT_FORMAT, ImageFormat.JPEG)
         imageCaptureConfig = builder.useCaseConfig
@@ -104,6 +106,31 @@
     }
 
     @Test
+    fun createPipeline_captureNodeHasImageReaderProxyProvider() {
+        // Arrange.
+        val imageReaderProxyProvider = ImageReaderProxyProvider { _, _, _, _, _ ->
+            FakeImageReaderProxy(MAX_IMAGES)
+        }
+        val builder = ImageCapture.Builder()
+            .setImageReaderProxyProvider(imageReaderProxyProvider)
+            .setCaptureOptionUnpacker { _, builder ->
+                builder.templateType = TEMPLATE_TYPE
+            }
+        builder.mutableConfig.insertOption(ImageInputConfig.OPTION_INPUT_FORMAT, ImageFormat.JPEG)
+        // Act.
+        val pipeline = ImagePipeline(builder.useCaseConfig, SIZE)
+        // Assert.
+        assertThat(pipeline.captureNode.inputEdge.imageReaderProxyProvider).isEqualTo(
+            imageReaderProxyProvider
+        )
+    }
+
+    @Test
+    fun createPipelineWithoutImageReaderProxyProvider_isNull() {
+        assertThat(imagePipeline.captureNode.inputEdge.imageReaderProxyProvider).isNull()
+    }
+
+    @Test
     fun createPipelineWithVirtualCamera_receivesImageProxy() {
         // Arrange: close the pipeline and create a new one not expecting metadata.
         imagePipeline.close()
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
index 3672fcd..b6c7ced 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
@@ -24,7 +24,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraProvider;
 import androidx.camera.core.CameraSelector;
@@ -277,7 +276,7 @@
      */
     // TODO: Will need to be rewritten to be threadsafe with use in conjunction with
     //  ExtensionsManager.init(...) if this is to be released for use outside of testing.
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public ListenableFuture<Void> shutdown() {
         synchronized (EXTENSIONS_LOCK) {
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
index 286acb9..7909211 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
@@ -36,8 +36,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.annotation.RestrictTo.Scope;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Camera;
 import androidx.camera.core.CameraEffect;
 import androidx.camera.core.CameraFilter;
@@ -283,7 +282,7 @@
      * future is a no-op.
      * @hide
      */
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public ListenableFuture<Void> shutdown() {
         runOnMainSync(this::unbindAll);
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
index 198e8c24..832c091 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
@@ -50,7 +50,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RequiresPermission;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
@@ -556,7 +556,7 @@
      * @param cameraCoordinator The camera coordinator for concurrent cameras.
      * @param cameraSelector The selector to select cameras with.
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public static CameraUseCaseAdapter createCameraUseCaseAdapter(
             @NonNull Context context,
@@ -591,7 +591,7 @@
      * @param context        The context used to initialize CameraX
      * @param cameraSelector The selector to select cameras with.
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public static CameraUseCaseAdapter createCameraUseCaseAdapter(
             @NonNull Context context,
@@ -616,7 +616,7 @@
      * @param cameraSelector The selector to select cameras with.
      * @param useCases       The UseCases to attach to the CameraUseCaseAdapter.
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public static CameraUseCaseAdapter createCameraAndAttachUseCase(
             @NonNull Context context,
diff --git a/camera/camera-video/api/current.txt b/camera/camera-video/api/current.txt
index 7611bce..f1af41e 100644
--- a/camera/camera-video/api/current.txt
+++ b/camera/camera-video/api/current.txt
@@ -139,7 +139,7 @@
     method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
     method public int getTargetRotation();
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     method public static <T extends androidx.camera.video.VideoOutput> androidx.camera.video.VideoCapture<T!> withOutput(T);
   }
 
diff --git a/camera/camera-video/api/public_plus_experimental_current.txt b/camera/camera-video/api/public_plus_experimental_current.txt
index 7611bce..f1af41e 100644
--- a/camera/camera-video/api/public_plus_experimental_current.txt
+++ b/camera/camera-video/api/public_plus_experimental_current.txt
@@ -139,7 +139,7 @@
     method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
     method public int getTargetRotation();
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     method public static <T extends androidx.camera.video.VideoOutput> androidx.camera.video.VideoCapture<T!> withOutput(T);
   }
 
diff --git a/camera/camera-video/api/restricted_current.txt b/camera/camera-video/api/restricted_current.txt
index 7611bce..f1af41e 100644
--- a/camera/camera-video/api/restricted_current.txt
+++ b/camera/camera-video/api/restricted_current.txt
@@ -139,7 +139,7 @@
     method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
     method public int getTargetRotation();
     method public void setTargetRotation(int);
-    method public void setTargetRotationDegrees(int);
+    method @Deprecated public void setTargetRotationDegrees(int);
     method public static <T extends androidx.camera.video.VideoOutput> androidx.camera.video.VideoCapture<T!> withOutput(T);
   }
 
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
index 7ee2e0b..9cfc292 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.media.MediaCodec
 import android.media.MediaCodecInfo
+import android.os.Build
 import androidx.camera.camera2.Camera2Config
 import androidx.camera.camera2.pipe.integration.CameraPipeConfig
 import androidx.camera.core.CameraSelector
@@ -118,13 +119,19 @@
 
             // Act.
             val (width, height) = videoProfile.width to videoProfile.height
+            // Pass if VideoCapabilities.isSizeSupported() is true
+            if (capabilities.isSizeSupported(width, height)) {
+                return@forEach
+            }
+
             val supportedWidths = capabilities.supportedWidths
             val supportedHeights = capabilities.supportedHeights
             val supportedWidthsForHeight = capabilities.getWidthsForHeightQuietly(height)
             val supportedHeightForWidth = capabilities.getHeightsForWidthQuietly(width)
 
             // Assert.
-            val msg = "mime: $mime, size: ${width}x$height is not in " +
+            val msg = "Build.BRAND: ${Build.BRAND}, Build.MODEL: ${Build.MODEL} " +
+                "mime: $mime, size: ${width}x$height is not in " +
                 "supported widths $supportedWidths/$supportedWidthsForHeight " +
                 "or heights $supportedHeights/$supportedHeightForWidth, " +
                 "the width/height alignment is " +
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt
index 7a13541..892b739 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt
@@ -222,6 +222,8 @@
 
     @Test
     fun addUseCases_setSupportedQuality_getCorrectResolution() = runBlocking {
+        assumeExtraCroppingQuirk(implName)
+
         val videoCapabilities = createFakeVideoCapabilities(supportedResolutionMap)
         assumeTrue(videoCapabilities.getSupportedQualities(dynamicRange).isNotEmpty())
         // Cuttlefish API 29 has inconsistent resolution issue. See b/184015059.
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
index ef0d4dc..2a79dbd 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
@@ -32,6 +32,7 @@
 import android.util.Rational
 import android.util.Size
 import android.view.Surface
+import androidx.annotation.RequiresApi
 import androidx.camera.camera2.Camera2Config
 import androidx.camera.camera2.pipe.integration.CameraPipeConfig
 import androidx.camera.core.AspectRatio
@@ -1063,13 +1064,7 @@
     }
 
     private fun assumeExtraCroppingQuirk() {
-        val msg =
-            "Devices in ExtraCroppingQuirk will get a fixed resolution regardless of any settings"
-        if (implName.contains(CameraPipeConfig::class.simpleName!!)) {
-            assumeTrue(msg, PipeDeviceQuirks[PipeExtraCroppingQuirk::class.java] == null)
-        } else {
-            assumeTrue(msg, Camera2DeviceQuirks.get(Camera2ExtraCroppingQuirk::class.java) == null)
-        }
+        assumeExtraCroppingQuirk(implName)
     }
 
     private class ImageSavedCallback :
@@ -1162,4 +1157,15 @@
     extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO) == "yes"
 
 internal fun MediaMetadataRetriever.getDuration(): Long? =
-    extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong()
\ No newline at end of file
+    extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong()
+
+@RequiresApi(21)
+fun assumeExtraCroppingQuirk(implName: String) {
+    val msg =
+        "Devices in ExtraCroppingQuirk will get a fixed resolution regardless of any settings"
+    if (implName.contains(CameraPipeConfig::class.simpleName!!)) {
+        assumeTrue(msg, PipeDeviceQuirks[PipeExtraCroppingQuirk::class.java] == null)
+    } else {
+        assumeTrue(msg, Camera2DeviceQuirks.get(Camera2ExtraCroppingQuirk::class.java) == null)
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSettingsAudioProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSettingsAudioProfileResolverTest.kt
index 4424a86..553e0a2 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSettingsAudioProfileResolverTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSettingsAudioProfileResolverTest.kt
@@ -40,6 +40,7 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
+import androidx.test.rule.GrantPermissionRule
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.TimeUnit
 import kotlinx.coroutines.Dispatchers
@@ -79,6 +80,11 @@
     }
 
     @get:Rule
+    val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
+        android.Manifest.permission.RECORD_AUDIO
+    )
+
+    @get:Rule
     val cameraPipeConfigTestRule = CameraPipeConfigTestRule(
         active = implName == CameraPipeConfig::class.simpleName,
     )
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
index c7a7b9b..8c83205 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
@@ -38,6 +38,7 @@
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_ZSL_DISABLED;
 import static androidx.camera.core.impl.utils.Threads.isMainThread;
 import static androidx.camera.core.impl.utils.TransformUtils.rectToString;
+import static androidx.camera.core.impl.utils.TransformUtils.within360;
 import static androidx.camera.core.internal.TargetConfig.OPTION_TARGET_CLASS;
 import static androidx.camera.core.internal.TargetConfig.OPTION_TARGET_NAME;
 import static androidx.camera.core.internal.ThreadConfig.OPTION_BACKGROUND_EXECUTOR;
@@ -247,13 +248,12 @@
      *
      * <p>The rotation can be set prior to constructing a VideoCapture using
      * {@link VideoCapture.Builder#setTargetRotation(int)} or dynamically by calling
-     * {@link VideoCapture#setTargetRotation(int)} or {@link #setTargetRotationDegrees(int)}.
+     * {@link VideoCapture#setTargetRotation(int)}.
      * If not set, the target rotation defaults to the value of {@link Display#getRotation()} of
      * the default display at the time the use case is bound.
      *
      * @return The rotation of the intended target.
      * @see VideoCapture#setTargetRotation(int)
-     * @see VideoCapture#setTargetRotationDegrees(int)
      */
     @RotationValue
     public int getTargetRotation() {
@@ -290,10 +290,11 @@
      * the target rotation. This way, the rotation output will indicate which way is down for a
      * given video. This is important since display orientation may be locked by device default,
      * user setting, or app configuration, and some devices may not transition to a
-     * reverse-portrait display orientation. In these cases, use
-     * {@link #setTargetRotationDegrees} to set target rotation dynamically according to the
-     * {@link android.view.OrientationEventListener}, without re-creating the use case.
-     * See {@link #setTargetRotationDegrees} for more information.
+     * reverse-portrait display orientation. In these cases, set target rotation dynamically
+     * according to the {@link android.view.OrientationEventListener}, without re-creating the
+     * use case. {@link UseCase#snapToSurfaceRotation(int)} is a helper function to convert the
+     * orientation of the {@link android.view.OrientationEventListener} to a rotation value.
+     * See {@link UseCase#snapToSurfaceRotation(int)} for more information and sample code.
      *
      * <p>If not set, the target rotation will default to the value of
      * {@link Display#getRotation()} of the default display at the time the use case is bound. To
@@ -385,9 +386,12 @@
      * will choose a strategy according to the use case.
      *
      * @param degrees Desired rotation degree of the output video.
+     * @deprecated Use {@link UseCase#snapToSurfaceRotation(int)} and
+     * {@link #setTargetRotation(int)} to convert and set the rotation.
      */
+    @Deprecated // TODO(b/277999375): Remove API setTargetRotationDegrees.
     public void setTargetRotationDegrees(int degrees) {
-        setTargetRotation(orientationDegreesToSurfaceRotation(degrees));
+        setTargetRotation(snapToSurfaceRotation(within360(degrees)));
     }
 
     /**
@@ -741,7 +745,7 @@
      *
      */
     @Nullable
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     SurfaceEdge getCameraEdge() {
         return mCameraEdge;
     }
@@ -1479,7 +1483,7 @@
          * Rotation values are relative to the "natural" rotation, {@link Surface#ROTATION_0}.
          *
          * <p>In general, it is best to additionally set the target rotation dynamically on the
-         * use case. See {@link VideoCapture#setTargetRotationDegrees(int)} for additional
+         * use case. See {@link VideoCapture#setTargetRotation(int)} for additional
          * documentation.
          *
          * <p>If not set, the target rotation will default to the value of
@@ -1495,7 +1499,6 @@
          * @param rotation The rotation of the intended target.
          * @return The current Builder.
          * @see VideoCapture#setTargetRotation(int)
-         * @see VideoCapture#setTargetRotationDegrees(int)
          * @see android.view.OrientationEventListener
          */
         @NonNull
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java
index 9f31996..557a2a7 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java
@@ -16,6 +16,9 @@
 
 package androidx.camera.video.internal.compat.quirk;
 
+import static android.media.MediaFormat.MIMETYPE_VIDEO_AVC;
+import static android.media.MediaFormat.MIMETYPE_VIDEO_MPEG4;
+
 import android.media.CamcorderProfile;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecList;
@@ -23,12 +26,17 @@
 import android.os.Build;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.camera.core.impl.Quirk;
 
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
 /**
  * <p>QuirkSummary
- *     Bug Id: 192431846, 199582287, 218841498, 203481899, 216583006
+ *     Bug Id: 192431846, 199582287, 218841498, 203481899, 216583006, 278843124, 278855948
  *     Description: Quirk which denotes {@link MediaCodecInfo} queried by {@link MediaCodecList}
  *                  returns incorrect info.
  *                  On Nokia 1, {@link CamcorderProfile} indicates it can support resolutions
@@ -55,19 +63,18 @@
  *                  experimental result, H.264 + 3840x2160 can be used to record video on this
  *                  device. Hence use quirk to workaround this case. See b/203481899#comment2.
  *                  @link MediaCodecInfo} searched by {@link MediaCodecList#getCodecInfos()}
- *                  shows the maximum supported resolution of the AVC encoder is 1920x1072 on
- *                  Redmi note 4 and LG K10 LTE K430. However, the 1920x1080 option can be
- *                  successfully configured properly. See b/216583006.
- *
+ *                  shows the maximum supported resolution of the AVC encoder is 1920x1072.
+ *                  However, the 1920x1080 option can be successfully configured properly.
+ *                  See b/216583006, b/278843124, b/278855948.
  *     Device(s): Nokia 1, Motc C, X650, LG-X230, Positivo Twist 2 Pro, Huawei Mate9, Redmi note 4
- *                , LG K10 LTE K430
+ *                , LG K10 LTE K430, Samsung Galaxy A03 Core, Vivo Y75, Realme C11 2021
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class MediaCodecInfoReportIncorrectInfoQuirk implements Quirk {
 
     static boolean load() {
         return isNokia1() || isMotoC() || isX650() || isX230() || isHuaweiMate9()
-                || isPositivoTwist2Pro() || isRedmiNote4() || isLGK430();
+                || isPositivoTwist2Pro() || isFHDProblematicDevice();
     }
 
     private static boolean isNokia1() {
@@ -96,39 +103,62 @@
                 Build.MODEL);
     }
 
-    private static boolean isRedmiNote4() {
-        return "Xiaomi".equalsIgnoreCase(Build.BRAND) && "redmi note 4".equalsIgnoreCase(
-                Build.MODEL);
-    }
-
-    private static boolean isLGK430() {
-        return "lge".equalsIgnoreCase(Build.BRAND) && "lg-k430".equalsIgnoreCase(Build.MODEL);
-    }
+    public static final List<String> INCORRECT_FHD_PROFILE_MODEL_LIST = Arrays.asList(
+            "lg-k430",
+            "redmi note 4",
+            "rmx3231",
+            "v2117",
+            "sm-a032f",
+            "moto g(20)",
+            "sm-a035m"
+    );
 
     /** Check if problematic MediaFormat info for these candidate devices. */
     public boolean isUnSupportMediaCodecInfo(@NonNull MediaFormat mediaFormat) {
+        MediaFormatResolver formatResolver = new MediaFormatResolver(mediaFormat);
         if (isNokia1() || isMotoC() || isX650() || isX230() || isPositivoTwist2Pro()) {
-            /** Checks if the given mime type is a problematic mime type. */
-            String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
-            return MediaFormat.MIMETYPE_VIDEO_MPEG4.equals(mimeType);
-        } else if (isHuaweiMate9() && isVideoFormat(mediaFormat)) {
-            /** Checks if this is an unsupported resolution for avc. */
-            int width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
-            int height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
-            return (width == 3840 && height == 2160);
-        } else if (isRedmiNote4() || isLGK430()) {
-            if (MediaFormat.MIMETYPE_VIDEO_AVC.equals(
-                    mediaFormat.getString(MediaFormat.KEY_MIME))) {
-                int width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
-                int height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
-                return width == 1920 && height == 1080;
-            }
+            return formatResolver.isMpeg4();
+        } else if (isHuaweiMate9()) {
+            return formatResolver.isVideo() && formatResolver.isSize(3840, 2160);
+        } else if (isFHDProblematicDevice()) {
+            return formatResolver.isAvc() && formatResolver.isSize(1920, 1080);
         }
         return false;
     }
 
-    private boolean isVideoFormat(@NonNull MediaFormat mediaFormat) {
-        String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
-        return mimeType.contains("video/");
+    private static boolean isFHDProblematicDevice() {
+        return INCORRECT_FHD_PROFILE_MODEL_LIST.contains(Build.MODEL.toLowerCase(Locale.US));
+    }
+
+    private static class MediaFormatResolver {
+        private final MediaFormat mMediaFormat;
+
+        MediaFormatResolver(@NonNull MediaFormat mediaFormat) {
+            mMediaFormat = mediaFormat;
+        }
+
+        boolean isVideo() {
+            String mimeType = getMime();
+            return mimeType != null && mimeType.contains("video/");
+        }
+
+        boolean isAvc() {
+            return MIMETYPE_VIDEO_AVC.equalsIgnoreCase(getMime());
+        }
+
+        boolean isMpeg4() {
+            return MIMETYPE_VIDEO_MPEG4.equalsIgnoreCase(getMime());
+        }
+
+        boolean isSize(int width, int height) {
+            int formatWidth = mMediaFormat.getInteger(MediaFormat.KEY_WIDTH);
+            int formatHeight = mMediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
+            return formatWidth == width && formatHeight == height;
+        }
+
+        @Nullable
+        private String getMime() {
+            return mMediaFormat.getString(MediaFormat.KEY_MIME);
+        }
     }
 }
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
index 7d1bb6d..93f2245 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
@@ -711,23 +711,6 @@
     }
 
     @Test
-    fun setTargetRotationDegrees() {
-        val videoCapture = createVideoCapture()
-        videoCapture.setTargetRotationDegrees(45)
-        assertThat(videoCapture.targetRotation).isEqualTo(Surface.ROTATION_270)
-        videoCapture.setTargetRotationDegrees(135)
-        assertThat(videoCapture.targetRotation).isEqualTo(Surface.ROTATION_180)
-        videoCapture.setTargetRotationDegrees(225)
-        assertThat(videoCapture.targetRotation).isEqualTo(Surface.ROTATION_90)
-        videoCapture.setTargetRotationDegrees(315)
-        assertThat(videoCapture.targetRotation).isEqualTo(Surface.ROTATION_0)
-        videoCapture.setTargetRotationDegrees(405)
-        assertThat(videoCapture.targetRotation).isEqualTo(Surface.ROTATION_270)
-        videoCapture.setTargetRotationDegrees(-45)
-        assertThat(videoCapture.targetRotation).isEqualTo(Surface.ROTATION_0)
-    }
-
-    @Test
     fun hasSurfaceProcessingQuirk_nodeIsNeeded() {
         // Arrange.
         VideoCapture.sEnableSurfaceProcessingByQuirk = true
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java b/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java
index 4a91e89..2f29672 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java
@@ -16,8 +16,6 @@
 
 package androidx.camera.view;
 
-import static androidx.annotation.RestrictTo.Scope.TESTS;
-
 import android.Manifest;
 import android.annotation.SuppressLint;
 import android.content.Context;
@@ -28,7 +26,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RequiresPermission;
-import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Camera;
 import androidx.camera.core.CameraEffect;
@@ -154,7 +151,7 @@
 
     /**
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     @SuppressWarnings("FutureReturnValueIgnored")
     void shutDownForTests() {
         if (mCameraProvider != null) {
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapper.java b/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapper.java
index 3247c70..b42e391 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapper.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapper.java
@@ -18,7 +18,7 @@
 
 import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Camera;
 import androidx.camera.core.CameraInfoUnavailableException;
 import androidx.camera.core.CameraSelector;
@@ -68,6 +68,6 @@
      *
      */
     @NonNull
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     ListenableFuture<Void> shutdown();
 }
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapperImpl.java b/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapperImpl.java
index fb13889..30b38fc 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapperImpl.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/ProcessCameraProviderWrapperImpl.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Camera;
 import androidx.camera.core.CameraInfoUnavailableException;
 import androidx.camera.core.CameraSelector;
@@ -66,6 +67,7 @@
         return mProcessCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);
     }
 
+    @VisibleForTesting
     @NonNull
     @Override
     public ListenableFuture<Void> shutdown() {
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FocusMeteringDeviceTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FocusMeteringDeviceTest.kt
index 42ed11b..056a07e 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FocusMeteringDeviceTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FocusMeteringDeviceTest.kt
@@ -17,12 +17,9 @@
 package androidx.camera.integration.core
 
 import android.content.Context
-import android.hardware.camera2.CameraCaptureSession
 import android.hardware.camera2.CameraCharacteristics.CONTROL_MAX_REGIONS_AE
 import android.hardware.camera2.CameraCharacteristics.CONTROL_MAX_REGIONS_AF
 import android.hardware.camera2.CameraCharacteristics.CONTROL_MAX_REGIONS_AWB
-import android.hardware.camera2.CaptureRequest
-import android.hardware.camera2.TotalCaptureResult
 import androidx.camera.camera2.Camera2Config
 import androidx.camera.camera2.pipe.integration.CameraPipeConfig
 import androidx.camera.core.Camera
@@ -35,7 +32,6 @@
 import androidx.camera.core.FocusMeteringAction.FLAG_AWB
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.SurfaceOrientedMeteringPointFactory
-import androidx.camera.integration.core.util.CameraPipeUtil
 import androidx.camera.lifecycle.ProcessCameraProvider
 import androidx.camera.testing.CameraPipeConfigTestRule
 import androidx.camera.testing.CameraUtil
@@ -45,7 +41,6 @@
 import androidx.test.filters.LargeTest
 import com.google.common.truth.Truth.assertThat
 import com.google.common.util.concurrent.ListenableFuture
-import java.util.concurrent.CountDownLatch
 import java.util.concurrent.ExecutionException
 import java.util.concurrent.TimeUnit
 import kotlinx.coroutines.Dispatchers
@@ -126,7 +121,6 @@
 
         ProcessCameraProvider.configureInstance(cameraXConfig)
         cameraProvider = ProcessCameraProvider.getInstance(context)[10, TimeUnit.SECONDS]
-        val captureCallback = CameraSessionCaptureCallback()
 
         withContext(Dispatchers.Main) {
             val fakeLifecycleOwner = FakeLifecycleOwner()
@@ -134,23 +128,9 @@
             camera = cameraProvider.bindToLifecycle(
                 fakeLifecycleOwner,
                 cameraSelector,
-                ImageCapture.Builder().also { builder ->
-                    captureCallback.let {
-                        CameraPipeUtil.setCameraCaptureSessionCallback(
-                            implName,
-                            builder,
-                            it
-                        )
-                    }
-                }.build()
+                ImageCapture.Builder().build()
             )
         }
-
-        if (implName == CameraPipeConfig::class.simpleName) {
-            // TODO(b/263211462): Remove this waiting for camera opening to be completed
-            //  when focus metering request can be submitted without the waiting
-            captureCallback.await(5000)
-        }
     }
 
     @After
@@ -434,22 +414,4 @@
             assertThat(cause).isInstanceOf(CameraControl.OperationCanceledException::class.java)
         }
     }
-
-    class CameraSessionCaptureCallback : CameraCaptureSession.CaptureCallback() {
-        private val latch = CountDownLatch(1)
-
-        override fun onCaptureCompleted(
-            session: CameraCaptureSession,
-            request: CaptureRequest,
-            result: TotalCaptureResult
-        ) {
-            latch.countDown()
-        }
-
-        suspend fun await(timeoutMs: Long = 10000) {
-            withContext(Dispatchers.IO) {
-                latch.await(timeoutMs, TimeUnit.MILLISECONDS)
-            }
-        }
-    }
 }
diff --git a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
index 81ea34c..610e9ae 100644
--- a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
+++ b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
@@ -136,6 +136,40 @@
     }
 
     @Test
+    fun enableEffect_previewEffectIsEnabled() {
+        // Arrange: launch app and verify effect is inactive.
+        fragment.assertPreviewIsStreaming()
+        val processor =
+            fragment.mToneMappingSurfaceEffect.surfaceProcessor as ToneMappingSurfaceProcessor
+        assertThat(processor.isSurfaceRequestedAndProvided()).isFalse()
+
+        // Act: turn on effect.
+        val effectToggleId = "androidx.camera.integration.view:id/effect_toggle"
+        uiDevice.findObject(UiSelector().resourceId(effectToggleId)).click()
+        instrumentation.waitForIdleSync()
+
+        // Assert: verify that effect is active.
+        assertThat(processor.isSurfaceRequestedAndProvided()).isTrue()
+    }
+
+    @Test
+    fun enableEffect_imageCaptureEffectIsEnabled() {
+        // Arrange: launch app and verify effect is inactive.
+        fragment.assertPreviewIsStreaming()
+        val effect = fragment.mToneMappingImageEffect as ToneMappingImageEffect
+        assertThat(effect.isInvoked()).isFalse()
+
+        // Act: turn on effect.
+        val effectToggleId = "androidx.camera.integration.view:id/effect_toggle"
+        uiDevice.findObject(UiSelector().resourceId(effectToggleId)).click()
+        instrumentation.waitForIdleSync()
+        fragment.assertCanTakePicture()
+
+        // Assert: verify that effect is active.
+        assertThat(effect.isInvoked()).isTrue()
+    }
+
+    @Test
     fun controllerBound_canGetCameraControl() {
         fragment.assertPreviewIsStreaming()
         instrumentation.runOnMainSync {
diff --git a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/EffectsFragmentTest.kt b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/EffectsFragmentTest.kt
deleted file mode 100644
index 85c2ca4..0000000
--- a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/EffectsFragmentTest.kt
+++ /dev/null
@@ -1,190 +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.camera.integration.view
-
-import android.net.Uri
-import android.os.Build
-import androidx.camera.camera2.Camera2Config
-import androidx.camera.camera2.pipe.integration.CameraPipeConfig
-import androidx.camera.core.CameraXConfig
-import androidx.camera.core.ImageCapture
-import androidx.camera.core.ImageCaptureException
-import androidx.camera.lifecycle.ProcessCameraProvider
-import androidx.camera.testing.CameraPipeConfigTestRule
-import androidx.camera.testing.CameraUtil
-import androidx.camera.testing.CoreAppTestUtil
-import androidx.camera.view.PreviewView
-import androidx.fragment.app.testing.FragmentScenario
-import androidx.lifecycle.Lifecycle
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.filters.LargeTest
-import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.GrantPermissionRule
-import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.Semaphore
-import java.util.concurrent.TimeUnit
-import org.junit.After
-import org.junit.Assume.assumeFalse
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-/**
- * Instrument tests for {@link EffectsFragment}.
- */
-@LargeTest
-@RunWith(Parameterized::class)
-class EffectsFragmentTest(
-    private val implName: String,
-    private val cameraConfig: CameraXConfig
-) {
-    @get:Rule
-    val cameraPipeConfigTestRule = CameraPipeConfigTestRule(
-        active = implName == CameraPipeConfig::class.simpleName,
-    )
-
-    @get:Rule
-    val useCameraRule = CameraUtil.grantCameraPermissionAndPreTest(
-        CameraControllerFragmentTest.testCameraRule,
-        CameraUtil.PreTestCameraIdList(cameraConfig)
-    )
-
-    @get:Rule
-    val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
-        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-        android.Manifest.permission.RECORD_AUDIO
-    )
-
-    private val instrumentation = InstrumentationRegistry.getInstrumentation()
-    private lateinit var cameraProvider: ProcessCameraProvider
-    private lateinit var fragment: EffectsFragment
-    private lateinit var fragmentScenario: FragmentScenario<EffectsFragment>
-
-    @Before
-    fun setup() {
-        // Clear the device UI and check if there is no dialog or lock screen on the top of the
-        // window before start the test.
-        CoreAppTestUtil.prepareDeviceUI(instrumentation)
-        ProcessCameraProvider.configureInstance(cameraConfig)
-        cameraProvider = ProcessCameraProvider.getInstance(
-            ApplicationProvider.getApplicationContext()
-        )[10000, TimeUnit.MILLISECONDS]
-        fragmentScenario = FragmentScenario.launchInContainer(
-            EffectsFragment::class.java, null, R.style.AppTheme,
-            null
-        )
-        fragment = fragmentScenario.getFragment()
-    }
-
-    @After
-    fun tearDown() {
-        if (::fragmentScenario.isInitialized) {
-            fragmentScenario.moveToState(Lifecycle.State.DESTROYED)
-        }
-
-        if (::cameraProvider.isInitialized) {
-            cameraProvider.shutdown()[10000, TimeUnit.MILLISECONDS]
-        }
-    }
-
-    @Test
-    fun launchFragment_surfaceProcessorIsActive() {
-        // Arrange.
-        fragment.assertPreviewStreaming()
-        // Assert.
-        assertThat(fragment.getSurfaceProcessor().isSurfaceRequestedAndProvided()).isTrue()
-    }
-
-    @Test
-    fun takePicture_imageEffectInvoked() {
-        // Arrange.
-        fragment.assertPreviewStreaming()
-        // Act.
-        fragment.assertCanTakePicture()
-        // Assert.
-        assertThat(fragment.getImageEffect()!!.isInvoked()).isTrue()
-    }
-
-    @Test
-    fun shareToImageCapture_canTakePicture() {
-        assumeFalse(
-            "Cuttlefish 31+ cannot take pictures. Unable to test.",
-            Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT >= 31
-        )
-        // Act.
-        instrumentation.runOnMainSync {
-            fragment.surfaceEffectForImageCapture.isChecked = true
-        }
-        // Assert.
-        fragment.assertPreviewStreaming()
-        fragment.assertCanTakePicture()
-        assertThat(fragment.getImageEffect()).isNull()
-    }
-
-    private fun FragmentScenario<EffectsFragment>.getFragment(): EffectsFragment {
-        var fragment: EffectsFragment? = null
-        this.onFragment { newValue: EffectsFragment -> fragment = newValue }
-        return fragment!!
-    }
-
-    private fun EffectsFragment.assertCanTakePicture() {
-        val imageCallbackSemaphore = Semaphore(0)
-        var uri: Uri? = null
-        instrumentation.runOnMainSync {
-            this.takePicture(object : ImageCapture.OnImageSavedCallback {
-                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
-                    uri = outputFileResults.savedUri
-                    imageCallbackSemaphore.release()
-                }
-
-                override fun onError(exception: ImageCaptureException) {
-                    throw exception
-                }
-            })
-        }
-        assertThat(imageCallbackSemaphore.tryAcquire(TIMEOUT_SECONDS, TimeUnit.SECONDS)).isTrue()
-        assertThat(uri).isNotNull()
-    }
-
-    private fun EffectsFragment.assertPreviewStreaming() {
-        val previewStreaming = Semaphore(0)
-        instrumentation.runOnMainSync {
-            previewView.previewStreamState.observe(
-                this
-            ) {
-                if (it == PreviewView.StreamState.STREAMING) {
-                    previewStreaming.release()
-                }
-            }
-        }
-        assertThat(previewStreaming.tryAcquire(TIMEOUT_SECONDS, TimeUnit.SECONDS)).isTrue()
-    }
-
-    companion object {
-
-        const val TIMEOUT_SECONDS = 10L
-
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun data() = listOf(
-            arrayOf(Camera2Config::class.simpleName, Camera2Config.defaultConfig()),
-            arrayOf(CameraPipeConfig::class.simpleName, CameraPipeConfig.defaultConfig())
-        )
-    }
-}
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
index 26550d3..1d771cc 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
@@ -20,6 +20,8 @@
 import static androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_NONE;
 
+import static java.util.Arrays.asList;
+
 import android.Manifest;
 import android.annotation.SuppressLint;
 import android.app.Dialog;
@@ -56,7 +58,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
 import androidx.annotation.RequiresPermission;
-import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImageAnalysis;
@@ -86,6 +87,7 @@
 import java.nio.ByteBuffer;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Locale;
 import java.util.Objects;
 import java.util.concurrent.ExecutorService;
@@ -108,6 +110,7 @@
     private FrameLayout mContainer;
     private Button mFlashMode;
     private ToggleButton mCameraToggle;
+    private ToggleButton mEffectToggle;
     private ExecutorService mExecutorService;
     private ToggleButton mCaptureEnabledToggle;
     private ToggleButton mAnalysisEnabledToggle;
@@ -145,6 +148,10 @@
     @Nullable
     private ImageAnalysis.Analyzer mWrappedAnalyzer;
 
+    @VisibleForTesting
+    ToneMappingSurfaceEffect mToneMappingSurfaceEffect;
+    ToneMappingImageEffect mToneMappingImageEffect;
+
     private final ImageAnalysis.Analyzer mAnalyzer = image -> {
         byte[] bytes = new byte[image.getPlanes()[0].getBuffer().remaining()];
         image.getPlanes()[0].getBuffer().get(bytes);
@@ -213,6 +220,13 @@
             }
         });
 
+        // Set up post-processing effects.
+        mToneMappingSurfaceEffect = new ToneMappingSurfaceEffect();
+        mToneMappingImageEffect = new ToneMappingImageEffect();
+        mEffectToggle = view.findViewById(R.id.effect_toggle);
+        mEffectToggle.setOnCheckedChangeListener((compoundButton, isChecked) -> onEffectsToggled());
+        onEffectsToggled();
+
         // Set up the button to change the PreviewView's size.
         view.findViewById(R.id.shrink).setOnClickListener(v -> {
             // Shrinks PreviewView by 10% each time it's clicked.
@@ -355,6 +369,16 @@
             mExecutorService.shutdown();
         }
         mRotationProvider.removeListener(mRotationListener);
+        mToneMappingSurfaceEffect.release();
+    }
+
+    private void onEffectsToggled() {
+        if (mEffectToggle.isChecked()) {
+            mCameraController.setEffects(
+                    new HashSet<>(asList(mToneMappingSurfaceEffect, mToneMappingImageEffect)));
+        } else {
+            mCameraController.clearEffects();
+        }
     }
 
     void checkFailedFuture(ListenableFuture<Void> voidFuture) {
@@ -585,22 +609,22 @@
     // For testing
     // -----------------
 
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     LifecycleCameraController getCameraController() {
         return mCameraController;
     }
 
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     void setWrappedAnalyzer(@Nullable ImageAnalysis.Analyzer analyzer) {
         mWrappedAnalyzer = analyzer;
     }
 
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     PreviewView getPreviewView() {
         return mPreviewView;
     }
 
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     int getSensorRotation() {
         return mRotation;
     }
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/EffectsFragment.kt b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/EffectsFragment.kt
deleted file mode 100644
index 4f5dbd9..0000000
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/EffectsFragment.kt
+++ /dev/null
@@ -1,251 +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.camera.integration.view
-
-import android.annotation.SuppressLint
-import android.content.ContentValues
-import android.os.Bundle
-import android.os.Environment
-import android.provider.MediaStore
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.RadioButton
-import android.widget.RadioGroup
-import android.widget.Toast
-import androidx.annotation.OptIn
-import androidx.annotation.VisibleForTesting
-import androidx.camera.core.CameraEffect
-import androidx.camera.core.CameraEffect.IMAGE_CAPTURE
-import androidx.camera.core.CameraEffect.PREVIEW
-import androidx.camera.core.CameraEffect.VIDEO_CAPTURE
-import androidx.camera.core.ImageCapture
-import androidx.camera.core.ImageCapture.OutputFileOptions
-import androidx.camera.core.ImageCaptureException
-import androidx.camera.core.impl.utils.executor.CameraXExecutors.directExecutor
-import androidx.camera.video.MediaStoreOutputOptions
-import androidx.camera.video.Recording
-import androidx.camera.video.VideoRecordEvent
-import androidx.camera.view.CameraController
-import androidx.camera.view.LifecycleCameraController
-import androidx.camera.view.PreviewView
-import androidx.camera.view.video.AudioConfig
-import androidx.camera.view.video.ExperimentalVideo
-import androidx.fragment.app.Fragment
-
-/**
- * Fragment for testing effects integration.
- */
-@OptIn(markerClass = [ExperimentalVideo::class])
-class EffectsFragment : Fragment() {
-
-    private lateinit var cameraController: LifecycleCameraController
-    lateinit var previewView: PreviewView
-    private lateinit var surfaceEffectForPreviewVideo: RadioButton
-    lateinit var surfaceEffectForImageCapture: RadioButton
-    private lateinit var imageEffectForImageCapture: RadioButton
-    private lateinit var previewVideoGroup: RadioGroup
-    private lateinit var imageGroup: RadioGroup
-    private lateinit var capture: Button
-    private lateinit var record: Button
-    private var recording: Recording? = null
-
-    private lateinit var surfaceProcessor: ToneMappingSurfaceProcessor
-    private var imageEffect: ToneMappingImageEffect? = null
-
-    override fun onCreateView(
-        inflater: LayoutInflater,
-        container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-        // Inflate the layout for this fragment.
-        val view = inflater.inflate(R.layout.effects_view, container, false)
-        previewView = view.findViewById(R.id.preview_view)
-        surfaceEffectForPreviewVideo = view.findViewById(R.id.surface_effect_for_preview_video)
-        surfaceEffectForImageCapture = view.findViewById(R.id.surface_effect_for_image_capture)
-        imageEffectForImageCapture = view.findViewById(R.id.image_effect_for_image_capture)
-        previewVideoGroup = view.findViewById(R.id.preview_and_video_effect_group)
-        imageGroup = view.findViewById(R.id.image_effect_group)
-        capture = view.findViewById(R.id.capture)
-        record = view.findViewById(R.id.record)
-
-        // Set up  UI events.
-        // previewView.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
-        previewVideoGroup.setOnCheckedChangeListener { _, _ -> updateEffects() }
-        imageGroup.setOnCheckedChangeListener { _, _ -> updateEffects() }
-        capture.setOnClickListener { takePicture() }
-        record.setOnClickListener {
-            if (recording == null) {
-                startRecording()
-            } else {
-                stopRecording()
-            }
-        }
-
-        // Set up the surface processor.
-        surfaceProcessor = ToneMappingSurfaceProcessor()
-
-        // Set up the camera controller.
-        cameraController = LifecycleCameraController(requireContext())
-        cameraController.setEnabledUseCases(
-            CameraController.IMAGE_CAPTURE or CameraController.VIDEO_CAPTURE
-        )
-        previewView.controller = cameraController
-        updateEffects()
-        cameraController.bindToLifecycle(viewLifecycleOwner)
-
-        return view
-    }
-
-    private fun updateEffects() {
-        val effects = mutableSetOf<CameraEffect>()
-        if (surfaceEffectForPreviewVideo.isChecked && surfaceEffectForImageCapture.isChecked) {
-            // Sharing surface effect to all 3 use cases
-            effects.add(
-                ToneMappingSurfaceEffect(
-                    PREVIEW or IMAGE_CAPTURE or VIDEO_CAPTURE,
-                    surfaceProcessor
-                )
-            )
-        } else if (surfaceEffectForPreviewVideo.isChecked) {
-            // Sharing surface effect to preview and video
-            effects.add(
-                ToneMappingSurfaceEffect(
-                    PREVIEW or VIDEO_CAPTURE,
-                    surfaceProcessor
-                )
-            )
-        } else if (
-            !surfaceEffectForPreviewVideo.isChecked && surfaceEffectForImageCapture.isChecked) {
-            toast(
-                "Cannot apply SurfaceProcessor to ImageCapture " +
-                    "without applying it to Preview and VideoCapture."
-            )
-        }
-
-        if (imageEffectForImageCapture.isChecked) {
-            // Use ImageEffect for image capture
-            imageEffect = ToneMappingImageEffect()
-            effects.add(imageEffect!!)
-        } else {
-            imageEffect = null
-        }
-        cameraController.setEffects(effects)
-    }
-
-    override fun onDestroy() {
-        super.onDestroy()
-        surfaceProcessor.release()
-    }
-
-    private fun toast(message: String?) {
-        requireActivity().runOnUiThread {
-            Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
-        }
-    }
-
-    private fun takePicture() {
-        takePicture(
-            object : ImageCapture.OnImageSavedCallback {
-                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
-                    toast("Image saved successfully.")
-                }
-
-                override fun onError(exception: ImageCaptureException) {
-                    toast("Image capture failed. $exception")
-                }
-            }
-        )
-    }
-
-    fun takePicture(onImageSavedCallback: ImageCapture.OnImageSavedCallback) {
-        createDefaultPictureFolderIfNotExist()
-        val contentValues = ContentValues()
-        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
-        val outputFileOptions = OutputFileOptions.Builder(
-            requireContext().contentResolver,
-            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
-            contentValues
-        ).build()
-        cameraController.takePicture(
-            outputFileOptions,
-            directExecutor(),
-            onImageSavedCallback
-        )
-    }
-
-    @SuppressLint("MissingPermission")
-    fun startRecording() {
-        record.text = "Stop recording"
-        val outputOptions: MediaStoreOutputOptions = getNewVideoOutputMediaStoreOptions()
-        val audioConfig = AudioConfig.create(true)
-        recording = cameraController.startRecording(
-            outputOptions, audioConfig,
-            directExecutor()
-        ) {
-            if (it is VideoRecordEvent.Finalize) {
-                val uri = it.outputResults.outputUri
-                if (it.error == VideoRecordEvent.Finalize.ERROR_NONE) {
-                    toast("Video saved to: $uri")
-                } else {
-                    toast("Failed to save video: uri $uri with code (${it.error})")
-                }
-            }
-        }
-    }
-
-    private fun stopRecording() {
-        record.text = "Record"
-        recording?.stop()
-    }
-
-    private fun getNewVideoOutputMediaStoreOptions(): MediaStoreOutputOptions {
-        val videoFileName = "video_" + System.currentTimeMillis()
-        val resolver = requireContext().contentResolver
-        val contentValues = ContentValues()
-        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
-        contentValues.put(MediaStore.Video.Media.TITLE, videoFileName)
-        contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName)
-        return MediaStoreOutputOptions.Builder(
-            resolver,
-            MediaStore.Video.Media.EXTERNAL_CONTENT_URI
-        ).setContentValues(contentValues)
-            .build()
-    }
-
-    private fun createDefaultPictureFolderIfNotExist() {
-        val pictureFolder = Environment.getExternalStoragePublicDirectory(
-            Environment.DIRECTORY_PICTURES
-        )
-        if (!pictureFolder.exists()) {
-            if (!pictureFolder.mkdir()) {
-                toast("Failed to create directory: $pictureFolder")
-            }
-        }
-    }
-
-    @VisibleForTesting
-    fun getImageEffect(): ToneMappingImageEffect? {
-        return imageEffect
-    }
-
-    @VisibleForTesting
-    fun getSurfaceProcessor(): ToneMappingSurfaceProcessor {
-        return surfaceProcessor
-    }
-}
\ No newline at end of file
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/MainActivity.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/MainActivity.java
index 6e40f89..970b5d8 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/MainActivity.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/MainActivity.java
@@ -190,9 +190,6 @@
             case R.id.mlkit:
                 mFragmentType = FragmentType.MLKIT;
                 break;
-            case R.id.effects:
-                mFragmentType = FragmentType.EFFECTS;
-                break;
         }
         startFragment();
         return true;
@@ -225,9 +222,6 @@
             case MLKIT:
                 startFragment(R.string.mlkit, new MlKitFragment());
                 break;
-            case EFFECTS:
-                startFragment(R.string.effects, new EffectsFragment());
-                break;
         }
     }
 
@@ -249,6 +243,6 @@
     }
 
     private enum FragmentType {
-        PREVIEW_VIEW, CAMERA_CONTROLLER, TRANSFORM, COMPOSE_UI, MLKIT, EFFECTS
+        PREVIEW_VIEW, CAMERA_CONTROLLER, TRANSFORM, COMPOSE_UI, MLKIT
     }
 }
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingImageEffect.kt b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingImageEffect.kt
index 6cb06f0..8f35484 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingImageEffect.kt
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingImageEffect.kt
@@ -35,15 +35,15 @@
 ) {
 
     fun isInvoked(): Boolean {
-        return (imageProcessor as ToneMappingImageProcessor).processed
+        return (imageProcessor as ToneMappingImageProcessor).processoed
     }
 
     private class ToneMappingImageProcessor : ImageProcessor {
 
-        var processed = false
+        var processoed = false
 
         override fun process(request: ImageProcessor.Request): Response {
-            processed = true
+            processoed = true
             val inputImage = request.inputImage as RgbaImageProxy
             val bitmap = inputImage.createBitmap()
             applyToneMapping(bitmap)
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceEffect.kt b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceEffect.kt
index 524a65f..3d18aff 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceEffect.kt
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceEffect.kt
@@ -22,15 +22,11 @@
 /**
  * A tone mapping effect for Preview/VideoCapture UseCase.
  */
-internal class ToneMappingSurfaceEffect(
-    targets: Int = PREVIEW or VIDEO_CAPTURE,
-    private val processor: ToneMappingSurfaceProcessor = ToneMappingSurfaceProcessor()
-) :
-    CameraEffect(
-        targets, mainThreadExecutor(), processor
-    ) {
+internal class ToneMappingSurfaceEffect : CameraEffect(
+    PREVIEW or VIDEO_CAPTURE, mainThreadExecutor(), ToneMappingSurfaceProcessor()
+) {
 
     fun release() {
-        (processor as? ToneMappingSurfaceProcessor)?.release()
+        (surfaceProcessor as? ToneMappingSurfaceProcessor)?.release()
     }
 }
\ No newline at end of file
diff --git a/camera/integration-tests/viewtestapp/src/main/res/layout-land/camera_controller_view.xml b/camera/integration-tests/viewtestapp/src/main/res/layout-land/camera_controller_view.xml
index f8cd281..127eedd 100644
--- a/camera/integration-tests/viewtestapp/src/main/res/layout-land/camera_controller_view.xml
+++ b/camera/integration-tests/viewtestapp/src/main/res/layout-land/camera_controller_view.xml
@@ -51,6 +51,12 @@
                 android:layout_height="wrap_content"
                 android:textOff="@string/toggle_camera_front"
                 android:textOn="@string/toggle_camera_back" />
+            <ToggleButton
+                android:id="@+id/effect_toggle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textOff="@string/toggle_effect_off"
+                android:textOn="@string/toggle_effect_on" />
         </LinearLayout>
 
         <LinearLayout
diff --git a/camera/integration-tests/viewtestapp/src/main/res/layout-land/effects_view.xml b/camera/integration-tests/viewtestapp/src/main/res/layout-land/effects_view.xml
deleted file mode 100644
index e854580..0000000
--- a/camera/integration-tests/viewtestapp/src/main/res/layout-land/effects_view.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  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.
-  -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <RelativeLayout
-        android:layout_width="0dp"
-        android:layout_weight="1"
-        android:layout_height="match_parent">
-        <androidx.camera.view.PreviewView
-            android:id="@+id/preview_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"/>
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true"
-            android:gravity="center_horizontal">
-            <Button
-                android:id="@+id/capture"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/btn_capture"
-                android:layout_margin="15dp"/>
-            <Button
-                android:id="@+id/record"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/btn_video_record"
-                android:layout_margin="15dp"/>
-        </LinearLayout>
-    </RelativeLayout>
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_margin="20dp">
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textStyle="bold"
-            android:text="@string/preview_and_video"/>
-        <RadioGroup
-            android:id="@+id/preview_and_video_effect_group"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content">
-            <RadioButton
-                android:id="@+id/surface_effect_for_preview_video"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:checked="true"
-                android:text="@string/surface_effect"/>
-            <RadioButton
-                android:id="@+id/no_effect_for_preview_video"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:checked="false"
-                android:text="@string/no_effect"/>
-        </RadioGroup>
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textStyle="bold"
-            android:layout_marginTop="20dp"
-            android:text="@string/image_capture"/>
-        <RadioGroup
-            android:id="@+id/image_effect_group"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content">
-            <RadioButton
-                android:id="@+id/surface_effect_for_image_capture"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:checked="false"
-                android:text="@string/surface_effect"/>
-            <RadioButton
-                android:id="@+id/image_effect_for_image_capture"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:checked="true"
-                android:text="@string/image_effect"/>
-            <RadioButton
-                android:id="@+id/no_effect_for_image_capture"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:checked="false"
-                android:text="@string/no_effect"/>
-        </RadioGroup>
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml b/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml
index d605440..abdbd23 100644
--- a/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml
+++ b/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml
@@ -48,6 +48,12 @@
             android:layout_height="wrap_content"
             android:textOff="@string/toggle_camera_front"
             android:textOn="@string/toggle_camera_back" />
+        <ToggleButton
+            android:id="@+id/effect_toggle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textOff="@string/toggle_effect_off"
+            android:textOn="@string/toggle_effect_on" />
     </LinearLayout>
 
     <LinearLayout
diff --git a/camera/integration-tests/viewtestapp/src/main/res/layout/effects_view.xml b/camera/integration-tests/viewtestapp/src/main/res/layout/effects_view.xml
deleted file mode 100644
index bb902eb..0000000
--- a/camera/integration-tests/viewtestapp/src/main/res/layout/effects_view.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  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.
-  -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_weight="1"
-        android:layout_height="0dp">
-        <androidx.camera.view.PreviewView
-            android:id="@+id/preview_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"/>
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true"
-            android:gravity="center_horizontal">
-            <Button
-                android:id="@+id/capture"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/btn_capture"
-                android:layout_margin="15dp"/>
-            <Button
-                android:id="@+id/record"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/btn_video_record"
-                android:layout_margin="15dp"/>
-        </LinearLayout>
-    </RelativeLayout>
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_margin="20dp">
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="0dp"
-            android:layout_weight="1"
-            android:layout_height="match_parent">
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textStyle="bold"
-                android:text="@string/preview_and_video"/>
-            <RadioGroup
-                android:id="@+id/preview_and_video_effect_group"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content">
-                <RadioButton
-                    android:id="@+id/surface_effect_for_preview_video"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:checked="true"
-                    android:text="@string/surface_effect"/>
-                <RadioButton
-                    android:id="@+id/no_effect_for_preview_video"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:checked="false"
-                    android:text="@string/no_effect"/>
-            </RadioGroup>
-        </LinearLayout>
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="0dp"
-            android:layout_weight="1"
-            android:layout_height="match_parent">
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textStyle="bold"
-                android:text="@string/image_capture"/>
-            <RadioGroup
-                android:id="@+id/image_effect_group"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content">
-                <RadioButton
-                    android:id="@+id/surface_effect_for_image_capture"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:checked="false"
-                    android:text="@string/surface_effect"/>
-                <RadioButton
-                    android:id="@+id/image_effect_for_image_capture"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:checked="true"
-                    android:text="@string/image_effect"/>
-                <RadioButton
-                    android:id="@+id/no_effect_for_image_capture"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:checked="false"
-                    android:text="@string/no_effect"/>
-            </RadioGroup>
-        </LinearLayout>
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/camera/integration-tests/viewtestapp/src/main/res/menu/actionbar_menu.xml b/camera/integration-tests/viewtestapp/src/main/res/menu/actionbar_menu.xml
index d736286..4a8d889 100644
--- a/camera/integration-tests/viewtestapp/src/main/res/menu/actionbar_menu.xml
+++ b/camera/integration-tests/viewtestapp/src/main/res/menu/actionbar_menu.xml
@@ -36,8 +36,4 @@
         android:id="@+id/mlkit"
         android:title="@string/mlkit"
         app:showAsAction="never" />
-    <item
-        android:id="@+id/effects"
-        android:title="@string/effects"
-        app:showAsAction="never" />
 </menu>
\ No newline at end of file
diff --git a/camera/integration-tests/viewtestapp/src/main/res/values/donottranslate-strings.xml b/camera/integration-tests/viewtestapp/src/main/res/values/donottranslate-strings.xml
index d70d3f8..1c62930 100644
--- a/camera/integration-tests/viewtestapp/src/main/res/values/donottranslate-strings.xml
+++ b/camera/integration-tests/viewtestapp/src/main/res/values/donottranslate-strings.xml
@@ -16,12 +16,7 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
 
     <string name="app_name">CameraX Views Demo</string>
-    <string name="preview_and_video">Preview &amp; Video</string>
-    <string name="effects">Effects</string>
-    <string name="surface_effect">Surface effect</string>
-    <string name="no_effect">No effect</string>
-    <string name="image_effect">Image effect</string>
-    <string name="image_capture">ImageCapture</string>
+
     <string name="preview">Preview</string>
     <string name="btn_capture">Capture</string>
     <string name="btn_video_record">Record</string>
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/ICarAppActivity.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/ICarAppActivity.aidl
new file mode 100644
index 0000000..26e7e22
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/ICarAppActivity.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer;
+/* @hide */
+interface ICarAppActivity {
+  oneway void setSurfacePackage(in androidx.car.app.serialization.Bundleable surfacePackage) = 1;
+  oneway void setSurfaceListener(androidx.car.app.activity.renderer.surface.ISurfaceListener listener) = 2;
+  oneway void registerRendererCallback(androidx.car.app.activity.renderer.IRendererCallback callback) = 3;
+  oneway void onStartInput() = 4;
+  oneway void onStopInput() = 5;
+  oneway void startCarApp(in android.content.Intent intent) = 6;
+  oneway void finishCarApp() = 7;
+  oneway void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd) = 8;
+  oneway void setInsetsListener(androidx.car.app.activity.renderer.IInsetsListener listener) = 9;
+  oneway void showAssist(in android.os.Bundle args) = 10;
+}
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IInsetsListener.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IInsetsListener.aidl
new file mode 100644
index 0000000..1f3159d
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IInsetsListener.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer;
+/* @hide */
+interface IInsetsListener {
+  /**
+   * @deprecated Use onWindowInsetsChanged(Insets, Insets) instead.
+   */
+  void onInsetsChanged(in android.graphics.Insets insets) = 1;
+  void onWindowInsetsChanged(in android.graphics.Insets insets, in android.graphics.Insets safeInsets) = 2;
+}
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IProxyInputConnection.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IProxyInputConnection.aidl
new file mode 100644
index 0000000..a0e60d4
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IProxyInputConnection.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer;
+/* @hide */
+interface IProxyInputConnection {
+  CharSequence getTextBeforeCursor(int length, int flags) = 1;
+  CharSequence getTextAfterCursor(int length, int flags) = 2;
+  CharSequence getSelectedText(int flags) = 3;
+  int getCursorCapsMode(int reqModes) = 4;
+  boolean deleteSurroundingText(int beforeLength, int afterLength) = 5;
+  boolean setComposingText(CharSequence text, int newCursorPosition) = 6;
+  boolean setComposingRegion(int start, int end) = 7;
+  boolean finishComposingText() = 8;
+  boolean commitText(CharSequence text, int newCursorPosition) = 9;
+  boolean setSelection(int start, int end) = 10;
+  boolean performEditorAction(int editorAction) = 11;
+  boolean performContextMenuAction(int id) = 12;
+  boolean beginBatchEdit() = 13;
+  boolean endBatchEdit() = 14;
+  boolean sendKeyEvent(in android.view.KeyEvent event) = 15;
+  boolean clearMetaKeyStates(int states) = 16;
+  boolean reportFullscreenMode(boolean enabled) = 17;
+  boolean performPrivateCommand(String action, in android.os.Bundle data) = 18;
+  boolean requestCursorUpdates(int cursorUpdateMode) = 19;
+  boolean commitCorrection(in android.view.inputmethod.CorrectionInfo correctionInfo) = 20;
+  boolean commitCompletion(in android.view.inputmethod.CompletionInfo text) = 21;
+  android.view.inputmethod.ExtractedText getExtractedText(in android.view.inputmethod.ExtractedTextRequest request, int flags) = 22;
+  void closeConnection() = 23;
+  android.view.inputmethod.EditorInfo getEditorInfo() = 24;
+}
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IRendererCallback.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IRendererCallback.aidl
new file mode 100644
index 0000000..8233bd1
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IRendererCallback.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer;
+/* @hide */
+interface IRendererCallback {
+  void onBackPressed() = 1;
+  void onCreate() = 2;
+  void onStart() = 3;
+  void onResume() = 4;
+  void onPause() = 5;
+  void onStop() = 6;
+  void onDestroyed() = 7;
+  androidx.car.app.activity.renderer.IProxyInputConnection onCreateInputConnection(in android.view.inputmethod.EditorInfo editorInfo) = 8;
+}
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IRendererService.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IRendererService.aidl
new file mode 100644
index 0000000..f2b84b8
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/IRendererService.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer;
+/* @hide */
+interface IRendererService {
+  boolean initialize(androidx.car.app.activity.renderer.ICarAppActivity carActivity, in android.content.ComponentName serviceName, int displayId) = 1;
+  boolean onNewIntent(in android.content.Intent intent, in android.content.ComponentName serviceName, int displayId) = 2;
+  void terminate(in android.content.ComponentName serviceName) = 3;
+  androidx.car.app.serialization.Bundleable performHandshake(in android.content.ComponentName serviceName, int appLatestApiLevel) = 4;
+}
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/surface/ISurfaceControl.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/surface/ISurfaceControl.aidl
new file mode 100644
index 0000000..700162d
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/surface/ISurfaceControl.aidl
@@ -0,0 +1,41 @@
+/**
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer.surface;
+/* @hide */
+interface ISurfaceControl {
+  oneway void setSurfaceWrapper(in androidx.car.app.serialization.Bundleable surfaceWrapper) = 1;
+  oneway void onTouchEvent(in android.view.MotionEvent event) = 2;
+  oneway void onWindowFocusChanged(boolean hasFocus, boolean isInTouchMode) = 3;
+  oneway void onKeyEvent(in android.view.KeyEvent event) = 4;
+}
diff --git a/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/surface/ISurfaceListener.aidl b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/surface/ISurfaceListener.aidl
new file mode 100644
index 0000000..582319c1
--- /dev/null
+++ b/car/app/app-automotive/api/aidlRelease/current/androidx/car/app/activity/renderer/surface/ISurfaceListener.aidl
@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package androidx.car.app.activity.renderer.surface;
+/* @hide */
+interface ISurfaceListener {
+  oneway void onSurfaceAvailable(in androidx.car.app.serialization.Bundleable surfaceWrapper) = 1;
+  oneway void onSurfaceChanged(in androidx.car.app.serialization.Bundleable surfaceWrapper) = 2;
+  oneway void onSurfaceDestroyed(in androidx.car.app.serialization.Bundleable surfaceWrapper) = 3;
+}
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/content/ComponentName.aidl b/car/app/app-automotive/src/main/stableAidlImports/android/content/ComponentName.aidl
deleted file mode 100644
index f1529b1..0000000
--- a/car/app/app-automotive/src/main/stableAidlImports/android/content/ComponentName.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.content;
-
-@JavaOnlyStableParcelable parcelable ComponentName;
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/content/Intent.aidl b/car/app/app-automotive/src/main/stableAidlImports/android/content/Intent.aidl
deleted file mode 100644
index 0c8c241..0000000
--- a/car/app/app-automotive/src/main/stableAidlImports/android/content/Intent.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.content;
-
-@JavaOnlyStableParcelable parcelable Intent;
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/os/Bundle.aidl b/car/app/app-automotive/src/main/stableAidlImports/android/os/Bundle.aidl
deleted file mode 100644
index 9642d31..0000000
--- a/car/app/app-automotive/src/main/stableAidlImports/android/os/Bundle.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.os;
-
-@JavaOnlyStableParcelable parcelable Bundle;
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
index fb180a2..e724acf 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
@@ -125,12 +125,12 @@
     <string name="package_not_found_error_msg" msgid="7525619456883627939">"ጥቅል አልተገኘም።"</string>
     <string name="permissions_granted_msg" msgid="2348556088141992714">"ሁሉም ፈቃዶች ተሰጥተዋል። እባክዎን ከቅንብሮች ፈቃዶችን ይሻሩ።"</string>
     <string name="needs_access_msg_prefix" msgid="2204136858798832382">"መተግበሪያው ለሚከተሉት ፈቃዶች መዳረሻ ያስፈልገዋል፦\n"</string>
-    <string name="phone_screen_permission_msg" msgid="3599815596923367256">"በስልኩ ማያ ገጽ ላይ ፈቃድ ይስጡ"</string>
+    <string name="phone_screen_permission_msg" msgid="3599815596923367256">"በስልኩ ማያ ገፅ ላይ ፈቃድ ይስጡ"</string>
     <string name="enable_location_permission_on_device_msg" msgid="472752487966156897">"በመሣሪያ ላይ የአካባቢ ፈቃዶችን አንቃ"</string>
-    <string name="enable_location_permission_on_phone_msg" msgid="5082615523959139121">"በስልኩ ማያ ገጽ ላይ አካባቢን አንቃ"</string>
+    <string name="enable_location_permission_on_phone_msg" msgid="5082615523959139121">"በስልኩ ማያ ገፅ ላይ አካባቢን አንቃ"</string>
     <string name="required_permissions_title" msgid="5351791879153568211">"የሚያስፈልጉ ፈቃዶች"</string>
     <string name="request_permissions_title" msgid="7456426341142412300">"የፈቃድ ቅንጭብ ማሳያን ጠይቅ"</string>
-    <string name="cancel_reservation_title" msgid="1374986823057959608">"የቦታ ማስያዣ ማይ ገጽ ይቅር"</string>
+    <string name="cancel_reservation_title" msgid="1374986823057959608">"የቦታ ማስያዣ ማይ ገፅ ይቅር"</string>
     <string name="reservation_cancelled_msg" msgid="6334213670275547875">"ቦታ ማስያዣ ተሰርዟል"</string>
     <string name="result_demo_title" msgid="3900525190662148290">"የውጤት ቅንጭብ ማሳያ"</string>
     <string name="not_started_for_result_msg" msgid="7498800528148447270">"ይህ መተግበሪያ ለውጤት አልተጀመረም"</string>
@@ -298,7 +298,7 @@
     <string name="some_additional_text" msgid="4009872495806318260">"አንዳንድ ተጨማሪ ጽሁፍ"</string>
     <string name="sample_additional_list" msgid="5085372891301576306">"የናሙና ሊመረጥ የሚችል ዝርዝር"</string>
     <string name="task_restriction_demo_title" msgid="2212084350718766941">"የተግባር ገደብ ቅንጭብ ማሳያ"</string>
-    <string name="task_limit_reached_msg" msgid="7162842196382260992">"ይህ የእርምጃ ቁጥር ፍሰቱ ከመጠን በላይ እንዲሆን ያደርገዋል እና ወደ አዲስ ማያ ገጽ ይመራዎታል።"</string>
+    <string name="task_limit_reached_msg" msgid="7162842196382260992">"ይህ የእርምጃ ቁጥር ፍሰቱ ከመጠን በላይ እንዲሆን ያደርገዋል እና ወደ አዲስ ማያ ገፅ ይመራዎታል።"</string>
     <string name="task_step_of_title" msgid="2791717962535723839">"የተግባር እርምጃ %1$d ከ%2$d"</string>
     <string name="task_step_of_text" msgid="4646729781462227219">"ወደፊት ለመሄድ ጠቅ ያድርጉ"</string>
     <string name="task_content_allowed" msgid="545061986612431190">"እባክዎ የተለያዩ የቅንብር ደንቦችን ይጎብኙ እና መኪናው የማሽከርከር ሁነታ ላይ እንደሆነ ያረጋግጡ"</string>
@@ -333,7 +333,7 @@
     <string name="showcase_demos_title" msgid="1542092687878113304">"የመሳያ ቅንጭብ ማሳያ"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"የቅንብር ደንብ አቀማመጥ ቅንጭብ ማሳያዎች"</string>
     <string name="grid_template_menu_demo_title" msgid="7096285873490705119">"የፍርግርግ ቅንብር ደንብ ቅንጭብ ማሳያዎች"</string>
-    <string name="voice_access_demo_title" msgid="3825223890895361496">"የድምጽ መዳረሻ ቅንጭብ ማሳያ ማያ ገጽ"</string>
+    <string name="voice_access_demo_title" msgid="3825223890895361496">"የድምጽ መዳረሻ ቅንጭብ ማሳያ ማያ ገፅ"</string>
     <string name="user_interactions_demo_title" msgid="1356952319161314986">"የተጠቃሚ መስተጋብሮች"</string>
     <string name="request_permission_menu_demo_title" msgid="4796486779527427017">"የቅንጭብ ማሳያ ፈቃዶችን ይጠይቁ"</string>
     <string name="application_overflow_title" msgid="396427940886169325">"የመተግበሪያ ትርፍ አረጋጋጭ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml
index 6a4c7b2a..5408e2f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml
@@ -226,7 +226,7 @@
     <string name="title_prefix" msgid="3991742709199357049">"標題"</string>
     <string name="list_template_demo_title" msgid="1740208242737246151">"「清單範本」示範"</string>
     <string name="long_msg_template_demo_title" msgid="1793748562161438131">"「長訊息範本」示範"</string>
-    <string name="long_msg_template_not_supported_text" msgid="3641559637317672505">"您的主機不支援「長訊息」範本"</string>
+    <string name="long_msg_template_not_supported_text" msgid="3641559637317672505">"你的主機不支援「長訊息」範本"</string>
     <string name="long_msg_template_not_supported_title" msgid="8600719470226274925">"主機不兼容"</string>
     <string name="msg_template_demo_title" msgid="3895210951340409473">"「訊息範本」示範"</string>
     <string name="msg_template_demo_text" msgid="2275291617716161409">"訊息會在這裡顯示。\n其他文字會在第二行顯示。"</string>
@@ -240,7 +240,7 @@
     <string name="google_sign_in" msgid="6556259799319701727">"Google 登入"</string>
     <string name="use_pin" msgid="7850893299484337431">"使用 PIN"</string>
     <string name="qr_code" msgid="5487041647280777397">"QR 碼"</string>
-    <string name="sign_in_template_not_supported_text" msgid="7184733753948837646">"您的主機不支援登入範本"</string>
+    <string name="sign_in_template_not_supported_text" msgid="7184733753948837646">"你的主機不支援登入範本"</string>
     <string name="sign_in_template_not_supported_title" msgid="4892883228898541764">"主機不兼容"</string>
     <string name="email_hint" msgid="7205549445477319606">"電郵"</string>
     <string name="sign_in_title" msgid="4551967308262681703">"登入"</string>
@@ -254,7 +254,7 @@
     <string name="qr_code_sign_in_title" msgid="8137070561006464518">"掃瞄 QR 碼即登入"</string>
     <string name="sign_in_with_google_title" msgid="8043752000786977249">"使用 Google 帳戶登入"</string>
     <string name="provider_sign_in_instruction" msgid="7586815688292506743">"使用這個按鈕可完成 Google 登入程序"</string>
-    <string name="sign_in_complete_text" msgid="8423984266325680606">"您已登入!"</string>
+    <string name="sign_in_complete_text" msgid="8423984266325680606">"你已登入!"</string>
     <string name="sign_in_complete_title" msgid="8919868148773983428">"已完成登入"</string>
     <string name="sign_in_template_demo_title" msgid="6052035424941410249">"「登入範本」示範"</string>
     <string name="tab_template_layouts_demo_title" msgid="6529681462424538165">"分頁範本示範"</string>
@@ -298,7 +298,7 @@
     <string name="some_additional_text" msgid="4009872495806318260">"一些其他文字"</string>
     <string name="sample_additional_list" msgid="5085372891301576306">"可選取的清單範本"</string>
     <string name="task_restriction_demo_title" msgid="2212084350718766941">"「工作限制」示範"</string>
-    <string name="task_limit_reached_msg" msgid="7162842196382260992">"這會導致步數超過上限,並將您向到新畫面。"</string>
+    <string name="task_limit_reached_msg" msgid="7162842196382260992">"這會導致步數超過上限,並將你向到新畫面。"</string>
     <string name="task_step_of_title" msgid="2791717962535723839">"工作步驟 %1$d,共 %2$d 個步驟"</string>
     <string name="task_step_of_text" msgid="4646729781462227219">"點擊即可繼續使用"</string>
     <string name="task_content_allowed" msgid="545061986612431190">"請查看各種範本,並確保汽車處於駕駛模式"</string>
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index c8ce9a4..ebb7251 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -660,6 +660,10 @@
     method public androidx.car.app.model.OnClickDelegate getOnClickDelegate();
   }
 
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public interface Content {
+    method public String getContentId();
+  }
+
   @androidx.car.app.annotations.CarProtocol public final class DateTimeWithZone {
     method public static androidx.car.app.model.DateTimeWithZone create(long, @IntRange(from=0xffff02e0, to=64800) int, String);
     method public static androidx.car.app.model.DateTimeWithZone create(long, java.util.TimeZone);
@@ -1064,6 +1068,60 @@
     method public androidx.car.app.model.ItemList getItemList();
   }
 
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public final class Tab implements androidx.car.app.model.Content {
+    method public String getContentId();
+    method public androidx.car.app.model.CarIcon getIcon();
+    method public androidx.car.app.model.CarText getTitle();
+  }
+
+  public static final class Tab.Builder {
+    ctor public Tab.Builder();
+    ctor public Tab.Builder(androidx.car.app.model.Tab);
+    method public androidx.car.app.model.Tab build();
+    method public androidx.car.app.model.Tab.Builder setContentId(String);
+    method public androidx.car.app.model.Tab.Builder setIcon(androidx.car.app.model.CarIcon);
+    method public androidx.car.app.model.Tab.Builder setTitle(CharSequence);
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public interface TabCallbackDelegate {
+    method public void sendTabSelected(String, androidx.car.app.OnDoneCallback);
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class TabContents implements androidx.car.app.model.Content {
+    method public String getContentId();
+    method public androidx.car.app.model.Template getTemplate();
+    field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
+  }
+
+  public static final class TabContents.Builder {
+    ctor public TabContents.Builder(androidx.car.app.model.Template);
+    method public androidx.car.app.model.TabContents build();
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class TabTemplate implements androidx.car.app.model.Template {
+    method public String getActiveTabContentId();
+    method public androidx.car.app.model.Action getHeaderAction();
+    method public androidx.car.app.model.TabCallbackDelegate getTabCallbackDelegate();
+    method public androidx.car.app.model.TabContents getTabContents();
+    method public java.util.List<androidx.car.app.model.Tab!> getTabs();
+    method public boolean isLoading();
+  }
+
+  public static final class TabTemplate.Builder {
+    ctor public TabTemplate.Builder(androidx.car.app.model.TabTemplate.TabCallback);
+    ctor public TabTemplate.Builder(androidx.car.app.model.TabTemplate);
+    method public androidx.car.app.model.TabTemplate.Builder addTab(androidx.car.app.model.Tab);
+    method public androidx.car.app.model.TabTemplate build();
+    method public androidx.car.app.model.TabTemplate.Builder setActiveTabContentId(String);
+    method public androidx.car.app.model.TabTemplate.Builder setHeaderAction(androidx.car.app.model.Action);
+    method public androidx.car.app.model.TabTemplate.Builder setLoading(boolean);
+    method public androidx.car.app.model.TabTemplate.Builder setTabContents(androidx.car.app.model.TabContents);
+  }
+
+  public static interface TabTemplate.TabCallback {
+    method public default void onTabSelected(String);
+  }
+
   @androidx.car.app.annotations.CarProtocol public interface Template {
   }
 
diff --git a/car/app/app/api/public_plus_experimental_current.txt b/car/app/app/api/public_plus_experimental_current.txt
index 02f26c1..0263505 100644
--- a/car/app/app/api/public_plus_experimental_current.txt
+++ b/car/app/app/api/public_plus_experimental_current.txt
@@ -866,7 +866,7 @@
 
 package androidx.car.app.messaging.model {
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class CarMessage {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(7) public class CarMessage {
     method public androidx.car.app.model.CarText getBody();
     method public long getReceivedTimeEpochMillis();
     method public androidx.core.app.Person? getSender();
@@ -887,12 +887,12 @@
     method public void onTextReply(String);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public interface ConversationCallbackDelegate {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(7) public interface ConversationCallbackDelegate {
     method public void sendMarkAsRead(androidx.car.app.OnDoneCallback);
     method public void sendTextReply(String, androidx.car.app.OnDoneCallback);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class ConversationItem implements androidx.car.app.model.Item {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(7) public class ConversationItem implements androidx.car.app.model.Item {
     method public androidx.car.app.messaging.model.ConversationCallbackDelegate getConversationCallbackDelegate();
     method public androidx.car.app.model.CarIcon? getIcon();
     method public String getId();
@@ -1097,7 +1097,7 @@
     method public androidx.car.app.model.OnClickDelegate getOnClickDelegate();
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public interface Content {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public interface Content {
     method public String getContentId();
   }
 
@@ -1525,7 +1525,7 @@
     method public androidx.car.app.model.ItemList getItemList();
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public final class Tab implements androidx.car.app.model.Content {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public final class Tab implements androidx.car.app.model.Content {
     method public String getContentId();
     method public androidx.car.app.model.CarIcon getIcon();
     method public androidx.car.app.model.CarText getTitle();
@@ -1540,11 +1540,11 @@
     method public androidx.car.app.model.Tab.Builder setTitle(CharSequence);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public interface TabCallbackDelegate {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public interface TabCallbackDelegate {
     method public void sendTabSelected(String, androidx.car.app.OnDoneCallback);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class TabContents implements androidx.car.app.model.Content {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class TabContents implements androidx.car.app.model.Content {
     method public String getContentId();
     method public androidx.car.app.model.Template getTemplate();
     field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
@@ -1555,7 +1555,7 @@
     method public androidx.car.app.model.TabContents build();
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class TabTemplate implements androidx.car.app.model.Template {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class TabTemplate implements androidx.car.app.model.Template {
     method public String getActiveTabContentId();
     method public androidx.car.app.model.Action getHeaderAction();
     method public androidx.car.app.model.TabCallbackDelegate getTabCallbackDelegate();
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index c8ce9a4..ebb7251 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -660,6 +660,10 @@
     method public androidx.car.app.model.OnClickDelegate getOnClickDelegate();
   }
 
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public interface Content {
+    method public String getContentId();
+  }
+
   @androidx.car.app.annotations.CarProtocol public final class DateTimeWithZone {
     method public static androidx.car.app.model.DateTimeWithZone create(long, @IntRange(from=0xffff02e0, to=64800) int, String);
     method public static androidx.car.app.model.DateTimeWithZone create(long, java.util.TimeZone);
@@ -1064,6 +1068,60 @@
     method public androidx.car.app.model.ItemList getItemList();
   }
 
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public final class Tab implements androidx.car.app.model.Content {
+    method public String getContentId();
+    method public androidx.car.app.model.CarIcon getIcon();
+    method public androidx.car.app.model.CarText getTitle();
+  }
+
+  public static final class Tab.Builder {
+    ctor public Tab.Builder();
+    ctor public Tab.Builder(androidx.car.app.model.Tab);
+    method public androidx.car.app.model.Tab build();
+    method public androidx.car.app.model.Tab.Builder setContentId(String);
+    method public androidx.car.app.model.Tab.Builder setIcon(androidx.car.app.model.CarIcon);
+    method public androidx.car.app.model.Tab.Builder setTitle(CharSequence);
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public interface TabCallbackDelegate {
+    method public void sendTabSelected(String, androidx.car.app.OnDoneCallback);
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class TabContents implements androidx.car.app.model.Content {
+    method public String getContentId();
+    method public androidx.car.app.model.Template getTemplate();
+    field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
+  }
+
+  public static final class TabContents.Builder {
+    ctor public TabContents.Builder(androidx.car.app.model.Template);
+    method public androidx.car.app.model.TabContents build();
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class TabTemplate implements androidx.car.app.model.Template {
+    method public String getActiveTabContentId();
+    method public androidx.car.app.model.Action getHeaderAction();
+    method public androidx.car.app.model.TabCallbackDelegate getTabCallbackDelegate();
+    method public androidx.car.app.model.TabContents getTabContents();
+    method public java.util.List<androidx.car.app.model.Tab!> getTabs();
+    method public boolean isLoading();
+  }
+
+  public static final class TabTemplate.Builder {
+    ctor public TabTemplate.Builder(androidx.car.app.model.TabTemplate.TabCallback);
+    ctor public TabTemplate.Builder(androidx.car.app.model.TabTemplate);
+    method public androidx.car.app.model.TabTemplate.Builder addTab(androidx.car.app.model.Tab);
+    method public androidx.car.app.model.TabTemplate build();
+    method public androidx.car.app.model.TabTemplate.Builder setActiveTabContentId(String);
+    method public androidx.car.app.model.TabTemplate.Builder setHeaderAction(androidx.car.app.model.Action);
+    method public androidx.car.app.model.TabTemplate.Builder setLoading(boolean);
+    method public androidx.car.app.model.TabTemplate.Builder setTabContents(androidx.car.app.model.TabContents);
+  }
+
+  public static interface TabTemplate.TabCallback {
+    method public default void onTabSelected(String);
+  }
+
   @androidx.car.app.annotations.CarProtocol public interface Template {
   }
 
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
index 034b5de..e81089d 100644
--- a/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
@@ -36,7 +36,7 @@
 /** Represents a single message in a {@link ConversationItem} */
 @ExperimentalCarApi
 @CarProtocol
-@RequiresCarApi(6)
+@RequiresCarApi(7)
 @KeepFields
 public class CarMessage {
     @Nullable
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegate.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegate.java
index 924e566..d9593c4 100644
--- a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegate.java
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegate.java
@@ -27,7 +27,7 @@
 /** Used by the host to invoke {@link ConversationCallback} methods on the client */
 @ExperimentalCarApi
 @CarProtocol
-@RequiresCarApi(6)
+@RequiresCarApi(7)
 public interface ConversationCallbackDelegate {
 
     /** Called from the host to invoke {@link ConversationCallback#onMarkAsRead()} on the client. */
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegateImpl.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegateImpl.java
index 5ab50b0..ffadaa1 100644
--- a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegateImpl.java
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationCallbackDelegateImpl.java
@@ -44,7 +44,7 @@
 @ExperimentalCarApi
 @RestrictTo(LIBRARY)
 @CarProtocol
-@RequiresCarApi(6)
+@RequiresCarApi(7)
 @KeepFields
 class ConversationCallbackDelegateImpl implements ConversationCallbackDelegate {
 
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
index b63b93e..c3962ef 100644
--- a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
@@ -43,7 +43,7 @@
 @ExperimentalCarApi
 @CarProtocol
 @KeepFields
-@RequiresCarApi(6)
+@RequiresCarApi(7)
 public class ConversationItem implements Item {
     @NonNull
     private final String mId;
diff --git a/car/app/app/src/main/java/androidx/car/app/model/Content.java b/car/app/app/src/main/java/androidx/car/app/model/Content.java
index 5023c429..c493b66 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/Content.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/Content.java
@@ -18,12 +18,10 @@
 
 import androidx.annotation.NonNull;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.RequiresCarApi;
 
 /** Interface implemented by models that can be invalidated and refreshed individually. */
 @CarProtocol
-@ExperimentalCarApi
 @RequiresCarApi(6)
 public interface Content {
 
diff --git a/car/app/app/src/main/java/androidx/car/app/model/Tab.java b/car/app/app/src/main/java/androidx/car/app/model/Tab.java
index d99fd60..f0292db 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/Tab.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/Tab.java
@@ -21,7 +21,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.KeepFields;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.constraints.CarIconConstraints;
@@ -34,7 +33,6 @@
  * display tab headers.
  */
 @CarProtocol
-@ExperimentalCarApi
 @RequiresCarApi(6)
 @KeepFields
 public final class Tab implements Content {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegate.java b/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegate.java
index ddb229b..6cf0bcb 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegate.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegate.java
@@ -21,7 +21,6 @@
 import androidx.annotation.NonNull;
 import androidx.car.app.OnDoneCallback;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.RequiresCarApi;
 
 /**
@@ -29,7 +28,6 @@
  * {@link androidx.car.app.model.TabTemplate.TabCallback} events to the car app.
  */
 @CarProtocol
-@ExperimentalCarApi
 @RequiresCarApi(6)
 public interface TabCallbackDelegate {
     /**
diff --git a/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegateImpl.java b/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegateImpl.java
index 4e559ca..ed7a988 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegateImpl.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/TabCallbackDelegateImpl.java
@@ -23,16 +23,14 @@
 import android.annotation.SuppressLint;
 import android.os.RemoteException;
 
-import androidx.annotation.Keep;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.car.app.IOnDoneCallback;
 import androidx.car.app.OnDoneCallback;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.annotations.ExperimentalCarApi;
-import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.annotations.KeepFields;
+import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.utils.RemoteUtils;
 
 /**
@@ -42,7 +40,6 @@
  */
 @RestrictTo(LIBRARY)
 @CarProtocol
-@ExperimentalCarApi
 @RequiresCarApi(6)
 @KeepFields
 public class TabCallbackDelegateImpl implements TabCallbackDelegate {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/TabContents.java b/car/app/app/src/main/java/androidx/car/app/model/TabContents.java
index d27dc30..b16cbd3 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/TabContents.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/TabContents.java
@@ -23,10 +23,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.annotations.ExperimentalCarApi;
+import androidx.car.app.annotations.KeepFields;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.constraints.TabContentsConstraints;
-import androidx.car.app.annotations.KeepFields;
 
 import java.util.Objects;
 
@@ -34,7 +33,6 @@
  * Represents the contents to display for a selected tab in a {@link TabTemplate}.
  */
 @CarProtocol
-@ExperimentalCarApi
 @RequiresCarApi(6)
 @KeepFields
 public class TabContents implements Content {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/TabTemplate.java b/car/app/app/src/main/java/androidx/car/app/model/TabTemplate.java
index 1a55793..e216793 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/TabTemplate.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/TabTemplate.java
@@ -26,7 +26,6 @@
 import androidx.annotation.Nullable;
 import androidx.car.app.Screen;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.KeepFields;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.constraints.TabsConstraints;
@@ -55,7 +54,6 @@
  * </ul>
  */
 @CarProtocol
-@ExperimentalCarApi
 @RequiresCarApi(6)
 @KeepFields
 public class TabTemplate implements Template {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java
index edf1329..a269ea2 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java
@@ -25,7 +25,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.Action;
 import androidx.car.app.model.Action.ActionType;
@@ -161,7 +160,6 @@
 
     /** Constraints for TabTemplate. */
     @NonNull
-    @ExperimentalCarApi
     @RequiresCarApi(6)
     public static final ActionsConstraints ACTIONS_CONSTRAINTS_TABS =
             new ActionsConstraints.Builder(ACTIONS_CONSTRAINTS_HEADER)
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java
index b1d917901..664eaa0 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java
@@ -18,7 +18,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.CarText;
 import androidx.car.app.model.GridTemplate;
@@ -37,7 +36,6 @@
  *
  * @hide
  */
-@ExperimentalCarApi
 @RequiresCarApi(6)
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class TabContentsConstraints {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/TabsConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/TabsConstraints.java
index d80ab48..83bcf62 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/TabsConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/TabsConstraints.java
@@ -18,7 +18,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
-import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.Tab;
 
@@ -31,7 +30,6 @@
  *
  * @hide
  */
-@ExperimentalCarApi
 @RequiresCarApi(6)
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class TabsConstraints {
diff --git a/collection/collection/api/current.txt b/collection/collection/api/current.txt
index 3fbf783..a16f02c8 100644
--- a/collection/collection/api/current.txt
+++ b/collection/collection/api/current.txt
@@ -63,16 +63,16 @@
     method public void addLast(E element);
     method public void clear();
     method public operator E get(int index);
-    method public E! getFirst();
-    method public E! getLast();
+    method public E getFirst();
+    method public E getLast();
     method public boolean isEmpty();
     method public E popFirst();
     method public E popLast();
     method public void removeFromEnd(int count);
     method public void removeFromStart(int count);
     method public int size();
-    property public final E! first;
-    property public final E! last;
+    property public final E first;
+    property public final E last;
   }
 
   public final class CircularIntArray {
diff --git a/collection/collection/api/public_plus_experimental_current.txt b/collection/collection/api/public_plus_experimental_current.txt
index 3fbf783..a16f02c8 100644
--- a/collection/collection/api/public_plus_experimental_current.txt
+++ b/collection/collection/api/public_plus_experimental_current.txt
@@ -63,16 +63,16 @@
     method public void addLast(E element);
     method public void clear();
     method public operator E get(int index);
-    method public E! getFirst();
-    method public E! getLast();
+    method public E getFirst();
+    method public E getLast();
     method public boolean isEmpty();
     method public E popFirst();
     method public E popLast();
     method public void removeFromEnd(int count);
     method public void removeFromStart(int count);
     method public int size();
-    property public final E! first;
-    property public final E! last;
+    property public final E first;
+    property public final E last;
   }
 
   public final class CircularIntArray {
diff --git a/collection/collection/api/restricted_current.txt b/collection/collection/api/restricted_current.txt
index 3fbf783..a16f02c8 100644
--- a/collection/collection/api/restricted_current.txt
+++ b/collection/collection/api/restricted_current.txt
@@ -63,16 +63,16 @@
     method public void addLast(E element);
     method public void clear();
     method public operator E get(int index);
-    method public E! getFirst();
-    method public E! getLast();
+    method public E getFirst();
+    method public E getLast();
     method public boolean isEmpty();
     method public E popFirst();
     method public E popLast();
     method public void removeFromEnd(int count);
     method public void removeFromStart(int count);
     method public int size();
-    property public final E! first;
-    property public final E! last;
+    property public final E first;
+    property public final E last;
   }
 
   public final class CircularIntArray {
diff --git a/compose/animation/animation-core/api/current.txt b/compose/animation/animation-core/api/current.txt
index ac05bf2..ae892a1 100644
--- a/compose/animation/animation-core/api/current.txt
+++ b/compose/animation/animation-core/api/current.txt
@@ -12,8 +12,8 @@
     method public T getTargetValue();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T? getUpperBound();
-    method public T! getValue();
-    method public T! getVelocity();
+    method public T getValue();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     method public suspend Object? snapTo(T targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
@@ -25,8 +25,8 @@
     property public final T targetValue;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public final T? upperBound;
-    property public final T! value;
-    property public final T! velocity;
+    property public final T value;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -104,7 +104,7 @@
     method public T getTargetValue();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T getValue();
-    method public T! getVelocity();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     method public androidx.compose.animation.core.AnimationState<T,V> toAnimationState();
@@ -115,7 +115,7 @@
     property public final T targetValue;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public final T value;
-    property public final T! velocity;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -140,7 +140,7 @@
     method public long getLastFrameTimeNanos();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T getValue();
-    method public T! getVelocity();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     property public final long finishedTimeNanos;
@@ -148,7 +148,7 @@
     property public final long lastFrameTimeNanos;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public T value;
-    property public final T! velocity;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -567,7 +567,7 @@
 
   @androidx.compose.runtime.Stable public final class Transition<S> {
     method public java.util.List<androidx.compose.animation.core.Transition<S>.TransitionAnimationState<?,?>> getAnimations();
-    method public S! getCurrentState();
+    method public S getCurrentState();
     method public String? getLabel();
     method public androidx.compose.animation.core.Transition.Segment<S> getSegment();
     method public S getTargetState();
@@ -575,7 +575,7 @@
     method public java.util.List<androidx.compose.animation.core.Transition<?>> getTransitions();
     method public boolean isRunning();
     property public final java.util.List<androidx.compose.animation.core.Transition<S>.TransitionAnimationState<?,?>> animations;
-    property public final S! currentState;
+    property public final S currentState;
     property public final boolean isRunning;
     property public final String? label;
     property public final androidx.compose.animation.core.Transition.Segment<S> segment;
diff --git a/compose/animation/animation-core/api/public_plus_experimental_current.txt b/compose/animation/animation-core/api/public_plus_experimental_current.txt
index 03897cb..7a2c3a4 100644
--- a/compose/animation/animation-core/api/public_plus_experimental_current.txt
+++ b/compose/animation/animation-core/api/public_plus_experimental_current.txt
@@ -12,8 +12,8 @@
     method public T getTargetValue();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T? getUpperBound();
-    method public T! getValue();
-    method public T! getVelocity();
+    method public T getValue();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     method public suspend Object? snapTo(T targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
@@ -25,8 +25,8 @@
     property public final T targetValue;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public final T? upperBound;
-    property public final T! value;
-    property public final T! velocity;
+    property public final T value;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -104,7 +104,7 @@
     method public T getTargetValue();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T getValue();
-    method public T! getVelocity();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     method public androidx.compose.animation.core.AnimationState<T,V> toAnimationState();
@@ -115,7 +115,7 @@
     property public final T targetValue;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public final T value;
-    property public final T! velocity;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -140,7 +140,7 @@
     method public long getLastFrameTimeNanos();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T getValue();
-    method public T! getVelocity();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     property public final long finishedTimeNanos;
@@ -148,7 +148,7 @@
     property public final long lastFrameTimeNanos;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public T value;
-    property public final T! velocity;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -573,7 +573,7 @@
 
   @androidx.compose.runtime.Stable public final class Transition<S> {
     method public java.util.List<androidx.compose.animation.core.Transition<S>.TransitionAnimationState<?,?>> getAnimations();
-    method public S! getCurrentState();
+    method public S getCurrentState();
     method public String? getLabel();
     method public androidx.compose.animation.core.Transition.Segment<S> getSegment();
     method public S getTargetState();
@@ -581,7 +581,7 @@
     method public java.util.List<androidx.compose.animation.core.Transition<?>> getTransitions();
     method public boolean isRunning();
     property public final java.util.List<androidx.compose.animation.core.Transition<S>.TransitionAnimationState<?,?>> animations;
-    property public final S! currentState;
+    property public final S currentState;
     property public final boolean isRunning;
     property public final String? label;
     property public final androidx.compose.animation.core.Transition.Segment<S> segment;
diff --git a/compose/animation/animation-core/api/restricted_current.txt b/compose/animation/animation-core/api/restricted_current.txt
index fa302aa..b2e9658 100644
--- a/compose/animation/animation-core/api/restricted_current.txt
+++ b/compose/animation/animation-core/api/restricted_current.txt
@@ -12,8 +12,8 @@
     method public T getTargetValue();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T? getUpperBound();
-    method public T! getValue();
-    method public T! getVelocity();
+    method public T getValue();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     method public suspend Object? snapTo(T targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
@@ -25,8 +25,8 @@
     property public final T targetValue;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public final T? upperBound;
-    property public final T! value;
-    property public final T! velocity;
+    property public final T value;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -104,7 +104,7 @@
     method public T getTargetValue();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T getValue();
-    method public T! getVelocity();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     method public androidx.compose.animation.core.AnimationState<T,V> toAnimationState();
@@ -115,7 +115,7 @@
     property public final T targetValue;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public final T value;
-    property public final T! velocity;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -140,7 +140,7 @@
     method public long getLastFrameTimeNanos();
     method public androidx.compose.animation.core.TwoWayConverter<T,V> getTypeConverter();
     method public T getValue();
-    method public T! getVelocity();
+    method public T getVelocity();
     method public V getVelocityVector();
     method public boolean isRunning();
     property public final long finishedTimeNanos;
@@ -148,7 +148,7 @@
     property public final long lastFrameTimeNanos;
     property public final androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter;
     property public T value;
-    property public final T! velocity;
+    property public final T velocity;
     property public final V velocityVector;
   }
 
@@ -568,7 +568,7 @@
   @androidx.compose.runtime.Stable public final class Transition<S> {
     ctor @kotlin.PublishedApi internal Transition(androidx.compose.animation.core.MutableTransitionState<S> transitionState, optional String? label);
     method public java.util.List<androidx.compose.animation.core.Transition<S>.TransitionAnimationState<?,?>> getAnimations();
-    method public S! getCurrentState();
+    method public S getCurrentState();
     method public String? getLabel();
     method public androidx.compose.animation.core.Transition.Segment<S> getSegment();
     method public S getTargetState();
@@ -576,7 +576,7 @@
     method public java.util.List<androidx.compose.animation.core.Transition<?>> getTransitions();
     method public boolean isRunning();
     property public final java.util.List<androidx.compose.animation.core.Transition<S>.TransitionAnimationState<?,?>> animations;
-    property public final S! currentState;
+    property public final S currentState;
     property public final boolean isRunning;
     property public final String? label;
     property public final androidx.compose.animation.core.Transition.Segment<S> segment;
diff --git a/compose/compiler/compiler-hosted/integration-tests/build.gradle b/compose/compiler/compiler-hosted/integration-tests/build.gradle
index 149e956..0ac6b78 100644
--- a/compose/compiler/compiler-hosted/integration-tests/build.gradle
+++ b/compose/compiler/compiler-hosted/integration-tests/build.gradle
@@ -32,9 +32,7 @@
 
     testCompileOnly(libs.kotlinCompiler)
     testRuntimeOnly(
-        project(
-           ":compose:compiler:compiler-hosted:integration-tests:kotlin-compiler-repackaged"
-        )
+        project(":compose:compiler:compiler-hosted:integration-tests:kotlin-compiler-repackaged")
     )
 
     // tools.jar required for com.sun.jdi
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
index 9eb33b2..c991670 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
@@ -112,6 +112,7 @@
             9701 to "1.5.0-alpha01",
             9801 to "1.5.0-alpha02",
             9901 to "1.5.0-alpha03",
+            10001 to "1.5.0-alpha04",
         )
 
         /**
@@ -124,7 +125,7 @@
          * The maven version string of this compiler. This string should be updated before/after every
          * release.
          */
-        const val compilerVersion: String = "1.4.6"
+        const val compilerVersion: String = "1.5.0-alpha04"
         private val minimumRuntimeVersion: String
             get() = runtimeVersionToMavenVersionTable[minimumRuntimeVersionInt] ?: "unknown"
     }
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/ArrangementTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/ArrangementTest.kt
new file mode 100644
index 0000000..8808486
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/ArrangementTest.kt
@@ -0,0 +1,97 @@
+/*
+ * 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.compose.foundation.layout
+
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@SmallTest
+@RunWith(Parameterized::class)
+class ArrangementTest(private val testParam: TestParam) {
+
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @Test
+    fun testArrangement() = with(testParam) {
+        with(actualArrangement) {
+            composeTestRule.density.arrange(
+                actualTotalSize,
+                actualSizes,
+                actualLayoutDirection,
+                actualOutPositions
+            )
+
+            assertThat(actualOutPositions).isEqualTo(expectedOutPositions)
+        }
+    }
+
+    @Suppress("ArrayInDataClass") // Used only in parameterized tests.
+    data class TestParam(
+        val actualArrangement: Arrangement.HorizontalOrVertical,
+        val actualTotalSize: Int,
+        val actualSizes: IntArray,
+        val actualLayoutDirection: LayoutDirection,
+        val actualOutPositions: IntArray,
+        val expectedOutPositions: IntArray,
+    )
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun data() = listOf<Any>(
+            TestParam(
+                actualArrangement = Arrangement.SpaceBetween,
+                actualTotalSize = 2376,
+                actualSizes = intArrayOf(108, 24),
+                actualLayoutDirection = LayoutDirection.Rtl,
+                actualOutPositions = intArrayOf(0, 0),
+                expectedOutPositions = intArrayOf(2268, 0),
+            ),
+            TestParam(
+                actualArrangement = Arrangement.SpaceBetween,
+                actualTotalSize = 2376,
+                actualSizes = intArrayOf(108),
+                actualLayoutDirection = LayoutDirection.Rtl,
+                actualOutPositions = intArrayOf(0),
+                expectedOutPositions = intArrayOf(2268),
+            ),
+            TestParam(
+                actualArrangement = Arrangement.SpaceBetween,
+                actualTotalSize = 2376,
+                actualSizes = intArrayOf(108, 24),
+                actualLayoutDirection = LayoutDirection.Ltr,
+                actualOutPositions = intArrayOf(0, 0),
+                expectedOutPositions = intArrayOf(0, 2352),
+            ),
+            TestParam(
+                actualArrangement = Arrangement.SpaceBetween,
+                actualTotalSize = 2376,
+                actualSizes = intArrayOf(108),
+                actualLayoutDirection = LayoutDirection.Ltr,
+                actualOutPositions = intArrayOf(0),
+                expectedOutPositions = intArrayOf(0),
+            ),
+        )
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnModifierTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnModifierTest.kt
new file mode 100644
index 0000000..ae3fbd6
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnModifierTest.kt
@@ -0,0 +1,442 @@
+/*
+ * 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.compose.foundation.layout
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Measured
+import androidx.compose.ui.layout.onPlaced
+import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.ui.layout.positionInParent
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class RowColumnModifierTest() {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun testRow_updatesOnAlignmentChange() {
+        var positionInParentY = 0f
+        var alignment by mutableStateOf(Alignment.Top)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(100.toDp())) {
+                    Row(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                    .size(
+                                        20.toDp(), if (index == 4) {
+                                            10.toDp()
+                                        } else {
+                                            20.toDp()
+                                        }
+                                    )
+                                    .align(alignment)
+                                    .onPlaced {
+                                        if (index == 4) {
+                                            val positionInParent = it.positionInParent()
+                                            positionInParentY = positionInParent.y
+                                        }
+                                    })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentY).isEqualTo(0)
+            alignment = Alignment.CenterVertically
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentY).isEqualTo(5)
+        }
+    }
+
+    @Test
+    fun testRow_updatesOnAlignByBlockChange() {
+        var positionInParentY = 0f
+        val alignByBlock: (Measured) -> Int = { _ -> 5 }
+        val alignByNewBlock: (Measured) -> Int = { _ -> 0 }
+        var alignment by mutableStateOf(alignByBlock)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(100.toDp())) {
+                    Row(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                    .size(
+                                        20.toDp(), if (index == 4) {
+                                            10.toDp()
+                                        } else {
+                                            20.toDp()
+                                        }
+                                    )
+                                    .alignBy(
+                                        if (index == 4) {
+                                            alignment
+                                        } else {
+                                            alignByBlock
+                                        }
+                                    )
+                                    .onPlaced {
+                                        if (index == 4) {
+                                            val positionInParent = it.positionInParent()
+                                            positionInParentY = positionInParent.y
+                                        }
+                                    })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentY).isEqualTo(0)
+            alignment = alignByNewBlock
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentY).isEqualTo(5)
+        }
+    }
+
+    @Test
+    fun testRow_updatesOnWeightChange() {
+        var width = 0
+        var fill by mutableStateOf(false)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(200.toDp())) {
+                    Row(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                    .size(
+                                        20.toDp()
+                                    )
+                                    .weight(1f, fill)
+                                    .onSizeChanged {
+                                        if (index > 0) {
+                                            Truth
+                                                .assertThat(it.width)
+                                                .isEqualTo(width)
+                                        } else {
+                                            width = it.width
+                                        }
+                                    })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(width).isEqualTo(20)
+            fill = true
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(width).isEqualTo(40)
+        }
+    }
+
+    @Test
+    fun testRow_updatesOnWeightAndAlignmentChange() {
+        var width = 0
+        var fill by mutableStateOf(false)
+        var positionInParentY = 0f
+        var alignment by mutableStateOf(Alignment.Top)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(200.toDp())) {
+                    Row(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                .size(
+                                    20.toDp(), if (index == 4) {
+                                        10.toDp()
+                                    } else {
+                                        20.toDp()
+                                    }
+                                )
+                                .weight(1f, fill)
+                                .onSizeChanged {
+                                    if (index > 0) {
+                                        Truth
+                                            .assertThat(it.width)
+                                            .isEqualTo(width)
+                                    } else {
+                                        width = it.width
+                                    }
+                                }
+                                .align(alignment)
+                                .onPlaced {
+                                    if (index == 4) {
+                                        val positionInParent = it.positionInParent()
+                                        positionInParentY = positionInParent.y
+                                    }
+                                })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(width).isEqualTo(20)
+            Truth.assertThat(positionInParentY).isEqualTo(0)
+            alignment = Alignment.CenterVertically
+            fill = true
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(width).isEqualTo(40)
+            Truth.assertThat(positionInParentY).isEqualTo(5)
+        }
+    }
+
+    @Test
+    fun testColumn_updatesOnAlignmentChange() {
+        var positionInParentX = 0f
+        var alignment by mutableStateOf(Alignment.Start)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(100.toDp())) {
+                    Column(
+                        Modifier
+                            .wrapContentWidth()
+                            .wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                    .size(
+                                        if (index == 4) {
+                                            10.toDp()
+                                        } else {
+                                            20.toDp()
+                                        },
+                                        20.toDp(),
+                                    )
+                                    .align(alignment)
+                                    .onPlaced {
+                                        if (index == 4) {
+                                            val positionInParent = it.positionInParent()
+                                            positionInParentX = positionInParent.x
+                                        }
+                                    })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentX).isEqualTo(0)
+            alignment = Alignment.CenterHorizontally
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentX).isEqualTo(5)
+        }
+    }
+
+    @Test
+    fun testColumn_updatesOnAlignByBlockChange() {
+        var positionInParentX = 0f
+        val alignByBlock: (Measured) -> Int = { _ -> 5 }
+        val alignByNewBlock: (Measured) -> Int = { _ -> 0 }
+        var alignment by mutableStateOf(alignByBlock)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(100.toDp())) {
+                    Column(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                    .size(
+                                        if (index == 4) {
+                                            10.toDp()
+                                        } else {
+                                            20.toDp()
+                                        }, 20.toDp()
+                                    )
+                                    .alignBy(
+                                        if (index == 4) {
+                                            alignment
+                                        } else {
+                                            alignByBlock
+                                        }
+                                    )
+                                    .onPlaced {
+                                        if (index == 4) {
+                                            val positionInParent = it.positionInParent()
+                                            positionInParentX = positionInParent.x
+                                        }
+                                    })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentX).isEqualTo(0)
+            alignment = alignByNewBlock
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(positionInParentX).isEqualTo(5)
+        }
+    }
+
+    @Test
+    fun testColumn_updatesOnWeightChange() {
+        var height = 0
+        var fill by mutableStateOf(false)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(200.toDp())) {
+                    Column(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                    .size(
+                                        20.toDp()
+                                    )
+                                    .weight(1f, fill)
+                                    .onSizeChanged {
+                                        if (index > 0) {
+                                            Truth
+                                                .assertThat(it.height)
+                                                .isEqualTo(height)
+                                        } else {
+                                            height = it.height
+                                        }
+                                    })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(height).isEqualTo(20)
+            fill = true
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(height).isEqualTo(40)
+        }
+    }
+
+    @Test
+    fun testColumn_updatesOnWeightAndAlignmentChange() {
+        var height = 0
+        var fill by mutableStateOf(false)
+        var positionInParentX = 0f
+        var alignment by mutableStateOf(Alignment.Start)
+
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(200.toDp())) {
+                    Column(
+                        Modifier.wrapContentHeight()
+                    ) {
+                        repeat(5) { index ->
+                            Box(
+                                Modifier
+                                .size(
+                                    if (index == 4) {
+                                        10.toDp()
+                                    } else {
+                                        20.toDp()
+                                    },
+                                    20.toDp(),
+                                )
+                                .weight(1f, fill)
+                                .onSizeChanged {
+                                    if (index > 0) {
+                                        Truth
+                                            .assertThat(it.height)
+                                            .isEqualTo(height)
+                                    } else {
+                                        height = it.height
+                                    }
+                                }
+                                .align(alignment)
+                                .onPlaced {
+                                    if (index == 4) {
+                                        val positionInParent = it.positionInParent()
+                                        positionInParentX = positionInParent.x
+                                    }
+                                })
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(height).isEqualTo(20)
+            Truth.assertThat(positionInParentX).isEqualTo(0)
+            alignment = Alignment.CenterHorizontally
+            fill = true
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(height).isEqualTo(40)
+            Truth.assertThat(positionInParentX).isEqualTo(5)
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt
index 8613205..80bd902 100644
--- a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt
@@ -48,6 +48,11 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlin.math.max
+import kotlin.math.min
+import kotlin.math.roundToInt
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
@@ -56,15 +61,11 @@
 import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-import kotlin.math.max
-import kotlin.math.min
-import kotlin.math.roundToInt
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class RowColumnTest : LayoutTest() {
+
     @Before
     fun before() {
         isDebugInspectorInfoEnabled = true
@@ -2540,7 +2541,51 @@
     }
 
     @Test
-    fun testRow_withSpaceBetweenArrangement() = with(density) {
+    fun testRow_withSpaceBetweenArrangement_singleItem() = with(density) {
+        val sizeDp = 50.toDp()
+
+        val drawLatch = CountDownLatch(2)
+        val childPosition = arrayOf(Offset(-1f, -1f))
+        val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
+        var parentLayoutCoordinates: LayoutCoordinates? = null
+        show {
+            Center {
+                Row(
+                    Modifier.fillMaxWidth().onGloballyPositioned { coordinates ->
+                        parentLayoutCoordinates = coordinates
+                        drawLatch.countDown()
+                    },
+                    horizontalArrangement = Arrangement.SpaceBetween
+                ) {
+                    for (i in 0 until childPosition.size) {
+                        Container(
+                            width = sizeDp,
+                            height = sizeDp,
+                            modifier = Modifier.onGloballyPositioned { coordinates ->
+                                childLayoutCoordinates[i] = coordinates
+                                drawLatch.countDown()
+                            }
+                        ) {
+                        }
+                    }
+                }
+            }
+        }
+        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+
+        calculateChildPositions(childPosition, parentLayoutCoordinates, childLayoutCoordinates)
+
+        val root = findComposeView()
+        waitForDraw(root)
+
+        assertEquals(
+            Offset(0f, 0f),
+            childPosition[0]
+        )
+    }
+
+    @Test
+    fun testRow_withSpaceBetweenArrangement_multipleItems() = with(density) {
         val sizeDp = 50.toDp()
         val size = sizeDp.roundToPx()
 
@@ -2559,7 +2604,7 @@
                     },
                     horizontalArrangement = Arrangement.SpaceBetween
                 ) {
-                    for (i in 0 until childPosition.size) {
+                    for (i in childPosition.indices) {
                         Container(
                             width = sizeDp,
                             height = sizeDp,
@@ -4513,7 +4558,55 @@
     }
 
     @Test
-    fun testRow_Rtl_arrangementSpaceBetween() = with(density) {
+    fun testRow_Rtl_arrangementSpaceBetween_singleItem() = with(density) {
+        val size = 100
+        val sizeDp = size.toDp()
+
+        val drawLatch = CountDownLatch(2)
+        val childPosition = Array(1) { Offset.Zero }
+        val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
+        var parentLayoutCoordinates: LayoutCoordinates? = null
+        show {
+            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+                Row(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .onGloballyPositioned { coordinates ->
+                            parentLayoutCoordinates = coordinates
+                            drawLatch.countDown()
+                        },
+                    horizontalArrangement = Arrangement.SpaceBetween
+                ) {
+                    for (i in childPosition.indices) {
+                        Container(
+                            width = sizeDp,
+                            height = sizeDp,
+                            modifier = Modifier.onGloballyPositioned { coordinates ->
+                                childLayoutCoordinates[i] = coordinates
+                                drawLatch.countDown()
+                            },
+                            content = {}
+                        )
+                    }
+                }
+            }
+        }
+        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+
+        calculateChildPositions(childPosition, parentLayoutCoordinates, childLayoutCoordinates)
+
+        val root = findComposeView()
+        waitForDraw(root)
+
+        val gap = root.width - size.toFloat()
+        assertEquals(
+            Offset(gap, 0f),
+            childPosition[0]
+        )
+    }
+
+    @Test
+    fun testRow_Rtl_arrangementSpaceBetween_multipleItems() = with(density) {
         val size = 100
         val sizeDp = size.toDp()
 
@@ -5672,6 +5765,7 @@
             ValueElement("fill", false)
         )
     }
+
     @Test
     fun testColumn_AlignInspectableValue() {
         val modifier = with(ColumnScopeInstance) { Modifier.align(Alignment.Start) }
@@ -5701,9 +5795,7 @@
             ValueElement("fill", false)
         )
     }
-    // endregion
 }
-
 private val TestHorizontalLine = HorizontalAlignmentLine(::min)
 private val TestVerticalLine = VerticalAlignmentLine(::min)
 
@@ -5770,4 +5862,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AlignmentLine.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AlignmentLine.kt
index 36aa00e..ca7cfe7 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AlignmentLine.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AlignmentLine.kt
@@ -211,11 +211,10 @@
         )
     }
 
-    override fun update(node: AlignmentLineOffsetDpNode): AlignmentLineOffsetDpNode {
+    override fun update(node: AlignmentLineOffsetDpNode) {
         node.alignmentLine = alignmentLine
         node.before = before
         node.after = after
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -287,11 +286,10 @@
         return inspectorInfo()
     }
 
-    override fun update(node: AlignmentLineOffsetTextUnitNode): AlignmentLineOffsetTextUnitNode {
+    override fun update(node: AlignmentLineOffsetTextUnitNode) {
         node.alignmentLine = alignmentLine
         node.before = before
         node.after = after
-        return node
     }
 }
 
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
index 023db20..a408742 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
@@ -26,6 +26,7 @@
 import kotlin.math.min
 import kotlin.math.roundToInt
 import androidx.compose.foundation.layout.internal.JvmDefaultWithCompatibility
+
 /**
  * Used to specify the arrangement of the layout's children in layouts like [Row] or [Column] in
  * the main axis direction (horizontal and vertical, respectively).
@@ -664,13 +665,18 @@
         outPosition: IntArray,
         reverseInput: Boolean
     ) {
+        if (size.isEmpty()) return
+
         val consumedSize = size.fold(0) { a, b -> a + b }
-        val gapSize = if (size.size > 1) {
-            (totalSize - consumedSize).toFloat() / (size.size - 1)
-        } else {
-            0f
-        }
+        val noOfGaps = maxOf(size.lastIndex, 1)
+        val gapSize = (totalSize - consumedSize).toFloat() / noOfGaps
+
         var current = 0f
+        if (reverseInput && size.size == 1) {
+            // If the layout direction is right-to-left and there is only one gap,
+            // we start current with the gap size. That forces the single item to be right-aligned.
+            current = gapSize
+        }
         size.forEachIndexed(reverseInput) { index, it ->
             outPosition[index] = current.roundToInt()
             current += it.toFloat() + gapSize
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AspectRatio.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AspectRatio.kt
index d42d7f0..bd8c46e 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AspectRatio.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/AspectRatio.kt
@@ -83,10 +83,9 @@
         )
     }
 
-    override fun update(node: AspectRatioNode): AspectRatioNode {
+    override fun update(node: AspectRatioNode) {
         node.aspectRatio = aspectRatio
         node.matchHeightConstraintsFirst = matchHeightConstraintsFirst
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() { inspectorInfo() }
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt
index f1d4a80..c70e44d 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt
@@ -269,10 +269,9 @@
         return BoxChildDataNode(alignment, matchParentSize)
     }
 
-    override fun update(node: BoxChildDataNode): BoxChildDataNode {
+    override fun update(node: BoxChildDataNode) {
         node.alignment = alignment
         node.matchParentSize = matchParentSize
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Column.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Column.kt
index 819c069..2a6ba7c 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Column.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Column.kt
@@ -25,8 +25,6 @@
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.Measured
 import androidx.compose.ui.layout.VerticalAlignmentLine
-import androidx.compose.ui.platform.debugInspectorInfo
-import androidx.compose.foundation.layout.internal.JvmDefaultWithCompatibility
 
 /**
  * A layout composable that places its children in a vertical sequence. For a layout composable
@@ -201,49 +199,31 @@
     override fun Modifier.weight(weight: Float, fill: Boolean): Modifier {
         require(weight > 0.0) { "invalid weight $weight; must be greater than zero" }
         return this.then(
-            LayoutWeightImpl(
+            LayoutWeightElement(
                 weight = weight,
-                fill = fill,
-                inspectorInfo = debugInspectorInfo {
-                    name = "weight"
-                    value = weight
-                    properties["weight"] = weight
-                    properties["fill"] = fill
-                }
+                fill = fill
             )
         )
     }
 
     @Stable
     override fun Modifier.align(alignment: Alignment.Horizontal) = this.then(
-        HorizontalAlignModifier(
-            horizontal = alignment,
-            inspectorInfo = debugInspectorInfo {
-                name = "align"
-                value = alignment
-            }
+        HorizontalAlignElement(
+            horizontal = alignment
         )
     )
 
     @Stable
     override fun Modifier.alignBy(alignmentLine: VerticalAlignmentLine) = this.then(
-        SiblingsAlignedModifier.WithAlignmentLine(
-            alignmentLine = alignmentLine,
-            inspectorInfo = debugInspectorInfo {
-                name = "alignBy"
-                value = alignmentLine
-            }
+        WithAlignmentLineElement(
+            alignmentLine = alignmentLine
         )
     )
 
     @Stable
     override fun Modifier.alignBy(alignmentLineBlock: (Measured) -> Int) = this.then(
-        SiblingsAlignedModifier.WithAlignmentLineBlock(
-            block = alignmentLineBlock,
-            inspectorInfo = debugInspectorInfo {
-                name = "alignBy"
-                value = alignmentLineBlock
-            }
+        WithAlignmentLineBlockElement(
+            block = alignmentLineBlock
         )
     )
 }
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Offset.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Offset.kt
index e0df7f5..4fa34b4 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Offset.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Offset.kt
@@ -151,10 +151,10 @@
         return OffsetNode(x, y, rtlAware)
     }
 
-    override fun update(node: OffsetNode): OffsetNode = node.also {
-        it.x = x
-        it.y = y
-        it.rtlAware = rtlAware
+    override fun update(node: OffsetNode) {
+        node.x = x
+        node.y = y
+        node.rtlAware = rtlAware
     }
 
     override fun equals(other: Any?): Boolean {
@@ -208,9 +208,9 @@
         return OffsetPxNode(offset, rtlAware)
     }
 
-    override fun update(node: OffsetPxNode): OffsetPxNode = node.also {
-        it.offset = offset
-        it.rtlAware = rtlAware
+    override fun update(node: OffsetPxNode) {
+        node.offset = offset
+        node.rtlAware = rtlAware
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
index b8bc7e1..60e3434 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
@@ -347,12 +347,12 @@
         return PaddingNode(start, top, end, bottom, rtlAware)
     }
 
-    override fun update(node: PaddingNode): PaddingNode = node.also {
-        it.start = start
-        it.top = top
-        it.end = end
-        it.bottom = bottom
-        it.rtlAware = rtlAware
+    override fun update(node: PaddingNode) {
+        node.start = start
+        node.top = top
+        node.end = end
+        node.bottom = bottom
+        node.rtlAware = rtlAware
     }
 
     override fun hashCode(): Int {
@@ -416,8 +416,8 @@
         return PaddingValuesModifier(paddingValues)
     }
 
-    override fun update(node: PaddingValuesModifier): PaddingValuesModifier = node.also {
-        it.paddingValues = paddingValues
+    override fun update(node: PaddingValuesModifier) {
+        node.paddingValues = paddingValues
     }
 
     override fun hashCode(): Int = paddingValues.hashCode()
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Row.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Row.kt
index 7a99435..1c7b93b 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Row.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Row.kt
@@ -16,18 +16,16 @@
 
 package androidx.compose.foundation.layout
 
-import androidx.compose.ui.layout.FirstBaseline
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.FirstBaseline
 import androidx.compose.ui.layout.HorizontalAlignmentLine
 import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Measured
-import androidx.compose.ui.platform.debugInspectorInfo
-import androidx.compose.foundation.layout.internal.JvmDefaultWithCompatibility
 
 /**
  * A layout composable that places its children in a horizontal sequence. For a layout composable
@@ -221,38 +219,24 @@
     override fun Modifier.weight(weight: Float, fill: Boolean): Modifier {
         require(weight > 0.0) { "invalid weight $weight; must be greater than zero" }
         return this.then(
-            LayoutWeightImpl(
+            LayoutWeightElement(
                 weight = weight,
-                fill = fill,
-                inspectorInfo = debugInspectorInfo {
-                    name = "weight"
-                    value = weight
-                    properties["weight"] = weight
-                    properties["fill"] = fill
-                }
+                fill = fill
             )
         )
     }
 
     @Stable
     override fun Modifier.align(alignment: Alignment.Vertical) = this.then(
-        VerticalAlignModifier(
-            vertical = alignment,
-            inspectorInfo = debugInspectorInfo {
-                name = "align"
-                value = alignment
-            }
+        VerticalAlignElement(
+            alignment
         )
     )
 
     @Stable
     override fun Modifier.alignBy(alignmentLine: HorizontalAlignmentLine) = this.then(
-        SiblingsAlignedModifier.WithAlignmentLine(
-            alignmentLine = alignmentLine,
-            inspectorInfo = debugInspectorInfo {
-                name = "alignBy"
-                value = alignmentLine
-            }
+        WithAlignmentLineElement(
+            alignmentLine = alignmentLine
         )
     )
 
@@ -260,12 +244,8 @@
     override fun Modifier.alignByBaseline() = alignBy(FirstBaseline)
 
     override fun Modifier.alignBy(alignmentLineBlock: (Measured) -> Int) = this.then(
-        SiblingsAlignedModifier.WithAlignmentLineBlock(
-            block = alignmentLineBlock,
-            inspectorInfo = debugInspectorInfo {
-                name = "alignBy"
-                value = alignmentLineBlock
-            }
+        WithAlignmentLineBlockElement(
+            block = alignmentLineBlock
         )
     )
 }
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnImpl.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnImpl.kt
index 0d625d7..ce9028a 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnImpl.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnImpl.kt
@@ -21,6 +21,7 @@
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.AlignmentLine
 import androidx.compose.ui.layout.IntrinsicMeasurable
 import androidx.compose.ui.layout.IntrinsicMeasureScope
@@ -29,10 +30,10 @@
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
 import androidx.compose.ui.layout.Measured
-import androidx.compose.ui.layout.ParentDataModifier
 import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.ParentDataModifierNode
 import androidx.compose.ui.platform.InspectorInfo
-import androidx.compose.ui.platform.InspectorValueInfo
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
@@ -628,22 +629,24 @@
     return crossAxisMax
 }
 
-internal class LayoutWeightImpl(
+internal class LayoutWeightElement(
     val weight: Float,
     val fill: Boolean,
-    inspectorInfo: InspectorInfo.() -> Unit
-) : ParentDataModifier, InspectorValueInfo(inspectorInfo) {
-    override fun Density.modifyParentData(parentData: Any?) =
-        ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
-            it.weight = weight
-            it.fill = fill
-        }
+) : ModifierNodeElement<LayoutWeightNode>() {
+    override fun create(): LayoutWeightNode {
+        return LayoutWeightNode(weight, fill)
+    }
 
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        val otherModifier = other as? LayoutWeightImpl ?: return false
-        return weight == otherModifier.weight &&
-            fill == otherModifier.fill
+    override fun update(node: LayoutWeightNode) {
+        node.weight = weight
+        node.fill = fill
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "weight"
+        value = weight
+        properties["weight"] = weight
+        properties["fill"] = fill
     }
 
     override fun hashCode(): Int {
@@ -652,102 +655,168 @@
         return result
     }
 
-    override fun toString(): String =
-        "LayoutWeightImpl(weight=$weight, fill=$fill)"
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        val otherModifier = other as? LayoutWeightElement ?: return false
+        return weight == otherModifier.weight &&
+            fill == otherModifier.fill
+    }
 }
 
-internal sealed class SiblingsAlignedModifier(
-    inspectorInfo: InspectorInfo.() -> Unit
-) : ParentDataModifier, InspectorValueInfo(inspectorInfo) {
+internal class LayoutWeightNode(
+    var weight: Float,
+    var fill: Boolean,
+) : ParentDataModifierNode, Modifier.Node() {
+    override fun Density.modifyParentData(parentData: Any?) =
+        ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
+            it.weight = weight
+            it.fill = fill
+        }
+}
+
+internal class WithAlignmentLineBlockElement(
+    val block: (Measured) -> Int
+) : ModifierNodeElement<SiblingsAlignedNode.WithAlignmentLineBlockNode>() {
+    override fun create(): SiblingsAlignedNode.WithAlignmentLineBlockNode {
+        return SiblingsAlignedNode.WithAlignmentLineBlockNode(block)
+    }
+
+    override fun update(node: SiblingsAlignedNode.WithAlignmentLineBlockNode) {
+        node.block = block
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        val otherModifier = other as? WithAlignmentLineBlockElement ?: return false
+        return block == otherModifier.block
+    }
+
+    override fun hashCode(): Int = block.hashCode()
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "alignBy"
+        value = block
+    }
+}
+
+internal class WithAlignmentLineElement(
+    val alignmentLine: AlignmentLine
+) : ModifierNodeElement<SiblingsAlignedNode.WithAlignmentLineNode>() {
+    override fun create(): SiblingsAlignedNode.WithAlignmentLineNode {
+        return SiblingsAlignedNode.WithAlignmentLineNode(alignmentLine)
+    }
+
+    override fun update(node: SiblingsAlignedNode.WithAlignmentLineNode) {
+        node.alignmentLine = alignmentLine
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "alignBy"
+        value = alignmentLine
+    }
+
+    override fun hashCode(): Int = alignmentLine.hashCode()
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        val otherModifier = other as? WithAlignmentLineElement ?: return false
+        return alignmentLine == otherModifier.alignmentLine
+    }
+}
+
+internal sealed class SiblingsAlignedNode : ParentDataModifierNode, Modifier.Node() {
     abstract override fun Density.modifyParentData(parentData: Any?): Any?
 
-    internal class WithAlignmentLineBlock(
-        val block: (Measured) -> Int,
-        inspectorInfo: InspectorInfo.() -> Unit
-    ) : SiblingsAlignedModifier(inspectorInfo) {
+    internal class WithAlignmentLineBlockNode(
+        var block: (Measured) -> Int,
+    ) : SiblingsAlignedNode() {
         override fun Density.modifyParentData(parentData: Any?): Any {
             return ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
                 it.crossAxisAlignment =
                     CrossAxisAlignment.Relative(AlignmentLineProvider.Block(block))
             }
         }
-
-        override fun equals(other: Any?): Boolean {
-            if (this === other) return true
-            val otherModifier = other as? WithAlignmentLineBlock ?: return false
-            return block == otherModifier.block
-        }
-
-        override fun hashCode(): Int = block.hashCode()
-
-        override fun toString(): String = "WithAlignmentLineBlock(block=$block)"
     }
 
-    internal class WithAlignmentLine(
-        val alignmentLine: AlignmentLine,
-        inspectorInfo: InspectorInfo.() -> Unit
-    ) : SiblingsAlignedModifier(inspectorInfo) {
+    internal class WithAlignmentLineNode(
+        var alignmentLine: AlignmentLine,
+    ) : SiblingsAlignedNode() {
         override fun Density.modifyParentData(parentData: Any?): Any {
             return ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
                 it.crossAxisAlignment =
                     CrossAxisAlignment.Relative(AlignmentLineProvider.Value(alignmentLine))
             }
         }
-
-        override fun equals(other: Any?): Boolean {
-            if (this === other) return true
-            val otherModifier = other as? WithAlignmentLine ?: return false
-            return alignmentLine == otherModifier.alignmentLine
-        }
-
-        override fun hashCode(): Int = alignmentLine.hashCode()
-
-        override fun toString(): String = "WithAlignmentLine(line=$alignmentLine)"
     }
 }
 
-internal class HorizontalAlignModifier(
-    val horizontal: Alignment.Horizontal,
-    inspectorInfo: InspectorInfo.() -> Unit
-) : ParentDataModifier, InspectorValueInfo(inspectorInfo) {
+internal class HorizontalAlignElement(
+    val horizontal: Alignment.Horizontal
+) : ModifierNodeElement<HorizontalAlignNode>() {
+    override fun create(): HorizontalAlignNode {
+        return HorizontalAlignNode(horizontal)
+    }
+
+    override fun update(node: HorizontalAlignNode) {
+        node.horizontal = horizontal
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "align"
+        value = horizontal
+    }
+    override fun hashCode(): Int = horizontal.hashCode()
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        val otherModifier = other as? HorizontalAlignElement ?: return false
+        return horizontal == otherModifier.horizontal
+    }
+}
+
+internal class HorizontalAlignNode(
+    var horizontal: Alignment.Horizontal
+) : ParentDataModifierNode, Modifier.Node() {
     override fun Density.modifyParentData(parentData: Any?): RowColumnParentData {
         return ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
             it.crossAxisAlignment = CrossAxisAlignment.horizontal(horizontal)
         }
     }
+}
+
+internal class VerticalAlignElement(
+    val alignment: Alignment.Vertical,
+) : ModifierNodeElement<VerticalAlignNode>() {
+    override fun create(): VerticalAlignNode {
+        return VerticalAlignNode(alignment)
+    }
+
+    override fun update(node: VerticalAlignNode) {
+        node.vertical = alignment
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "align"
+        value = alignment
+    }
+
+    override fun hashCode(): Int = alignment.hashCode()
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
-        val otherModifier = other as? HorizontalAlignModifier ?: return false
-        return horizontal == otherModifier.horizontal
+        val otherModifier = other as? VerticalAlignElement ?: return false
+        return alignment == otherModifier.alignment
     }
-
-    override fun hashCode(): Int = horizontal.hashCode()
-
-    override fun toString(): String =
-        "HorizontalAlignModifier(horizontal=$horizontal)"
 }
 
-internal class VerticalAlignModifier(
-    val vertical: Alignment.Vertical,
-    inspectorInfo: InspectorInfo.() -> Unit
-) : ParentDataModifier, InspectorValueInfo(inspectorInfo) {
+internal class VerticalAlignNode(
+    var vertical: Alignment.Vertical
+) : ParentDataModifierNode, Modifier.Node() {
     override fun Density.modifyParentData(parentData: Any?): RowColumnParentData {
         return ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
             it.crossAxisAlignment = CrossAxisAlignment.vertical(vertical)
         }
     }
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        val otherModifier = other as? VerticalAlignModifier ?: return false
-        return vertical == otherModifier.vertical
-    }
-
-    override fun hashCode(): Int = vertical.hashCode()
-
-    override fun toString(): String =
-        "VerticalAlignModifier(vertical=$vertical)"
 }
 
 /**
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Size.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Size.kt
index 3fd65398..78210e2 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Size.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Size.kt
@@ -615,9 +615,9 @@
 ) : ModifierNodeElement<FillNode>() {
     override fun create(): FillNode = FillNode(direction = direction, fraction = fraction)
 
-    override fun update(node: FillNode): FillNode = node.also {
-        it.direction = direction
-        it.fraction = fraction
+    override fun update(node: FillNode) {
+        node.direction = direction
+        node.fraction = fraction
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -723,12 +723,12 @@
             enforceIncoming = enforceIncoming
         )
 
-    override fun update(node: SizeNode): SizeNode = node.also {
-        it.minWidth = minWidth
-        it.minHeight = minHeight
-        it.maxWidth = maxWidth
-        it.maxHeight = maxHeight
-        it.enforceIncoming = enforceIncoming
+    override fun update(node: SizeNode) {
+        node.minWidth = minWidth
+        node.minHeight = minHeight
+        node.maxWidth = maxWidth
+        node.maxHeight = maxHeight
+        node.enforceIncoming = enforceIncoming
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -903,10 +903,10 @@
         alignmentCallback
     )
 
-    override fun update(node: WrapContentNode): WrapContentNode = node.also {
-        it.direction = direction
-        it.unbounded = unbounded
-        it.alignmentCallback = alignmentCallback
+    override fun update(node: WrapContentNode) {
+        node.direction = direction
+        node.unbounded = unbounded
+        node.alignmentCallback = alignmentCallback
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -1029,9 +1029,9 @@
         minHeight = minHeight
     )
 
-    override fun update(node: UnspecifiedConstraintsNode) = node.also {
-        it.minWidth = minWidth
-        it.minHeight = minHeight
+    override fun update(node: UnspecifiedConstraintsNode) {
+        node.minWidth = minWidth
+        node.minHeight = minHeight
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 2a1b29f..337b887 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -494,6 +494,11 @@
     method public java.util.List<java.lang.Integer> calculateCrossAxisCellSizes(androidx.compose.ui.unit.Density, int availableSize, int spacing);
   }
 
+  public static final class GridCells.FixedSize implements androidx.compose.foundation.lazy.grid.GridCells {
+    ctor public GridCells.FixedSize(float size);
+    method public java.util.List<java.lang.Integer> calculateCrossAxisCellSizes(androidx.compose.ui.unit.Density, int availableSize, int spacing);
+  }
+
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class GridItemSpan {
     method public int getCurrentLineSpan();
   }
@@ -631,7 +636,7 @@
     property public abstract long size;
   }
 
-  public sealed interface LazyStaggeredGridItemScope {
+  @androidx.compose.runtime.Stable public sealed interface LazyStaggeredGridItemScope {
   }
 
   public sealed interface LazyStaggeredGridLayoutInfo {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 1bd8088..1143e67 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -371,8 +371,12 @@
 
 package androidx.compose.foundation.gestures.snapping {
 
+  public final class LazyGridSnapLayoutInfoProviderKt {
+    method @androidx.compose.foundation.ExperimentalFoundationApi public static androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider SnapLayoutInfoProvider(androidx.compose.foundation.lazy.grid.LazyGridState lazyGridState, optional androidx.compose.foundation.gestures.snapping.SnapPositionInLayout positionInLayout);
+  }
+
   public final class LazyListSnapLayoutInfoProviderKt {
-    method @androidx.compose.foundation.ExperimentalFoundationApi public static androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider SnapLayoutInfoProvider(androidx.compose.foundation.lazy.LazyListState lazyListState, optional kotlin.jvm.functions.Function3<? super androidx.compose.ui.unit.Density,? super java.lang.Float,? super java.lang.Float,java.lang.Float> positionInLayout);
+    method @androidx.compose.foundation.ExperimentalFoundationApi public static androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider SnapLayoutInfoProvider(androidx.compose.foundation.lazy.LazyListState lazyListState, optional androidx.compose.foundation.gestures.snapping.SnapPositionInLayout positionInLayout);
     method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.gestures.FlingBehavior rememberSnapFlingBehavior(androidx.compose.foundation.lazy.LazyListState lazyListState);
   }
 
@@ -392,6 +396,16 @@
     method public float calculateSnappingOffset(androidx.compose.ui.unit.Density, float currentVelocity);
   }
 
+  @androidx.compose.foundation.ExperimentalFoundationApi public fun interface SnapPositionInLayout {
+    method public int position(androidx.compose.ui.unit.Density, int layoutSize, int itemSize, int itemIndex);
+    field public static final androidx.compose.foundation.gestures.snapping.SnapPositionInLayout.Companion Companion;
+  }
+
+  public static final class SnapPositionInLayout.Companion {
+    method public androidx.compose.foundation.gestures.snapping.SnapPositionInLayout getCenterToCenter();
+    property public final androidx.compose.foundation.gestures.snapping.SnapPositionInLayout CenterToCenter;
+  }
+
 }
 
 package androidx.compose.foundation.interaction {
@@ -614,7 +628,7 @@
     method public java.util.List<java.lang.Integer> calculateCrossAxisCellSizes(androidx.compose.ui.unit.Density, int availableSize, int spacing);
   }
 
-  @androidx.compose.foundation.ExperimentalFoundationApi public static final class GridCells.FixedSize implements androidx.compose.foundation.lazy.grid.GridCells {
+  public static final class GridCells.FixedSize implements androidx.compose.foundation.lazy.grid.GridCells {
     ctor public GridCells.FixedSize(float size);
     method public java.util.List<java.lang.Integer> calculateCrossAxisCellSizes(androidx.compose.ui.unit.Density, int availableSize, int spacing);
   }
@@ -865,7 +879,8 @@
     property public abstract long size;
   }
 
-  public sealed interface LazyStaggeredGridItemScope {
+  @androidx.compose.runtime.Stable public sealed interface LazyStaggeredGridItemScope {
+    method @androidx.compose.foundation.ExperimentalFoundationApi public androidx.compose.ui.Modifier animateItemPlacement(androidx.compose.ui.Modifier, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec);
   }
 
   public sealed interface LazyStaggeredGridLayoutInfo {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 2a1b29f..337b887 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -494,6 +494,11 @@
     method public java.util.List<java.lang.Integer> calculateCrossAxisCellSizes(androidx.compose.ui.unit.Density, int availableSize, int spacing);
   }
 
+  public static final class GridCells.FixedSize implements androidx.compose.foundation.lazy.grid.GridCells {
+    ctor public GridCells.FixedSize(float size);
+    method public java.util.List<java.lang.Integer> calculateCrossAxisCellSizes(androidx.compose.ui.unit.Density, int availableSize, int spacing);
+  }
+
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class GridItemSpan {
     method public int getCurrentLineSpan();
   }
@@ -631,7 +636,7 @@
     property public abstract long size;
   }
 
-  public sealed interface LazyStaggeredGridItemScope {
+  @androidx.compose.runtime.Stable public sealed interface LazyStaggeredGridItemScope {
   }
 
   public sealed interface LazyStaggeredGridLayoutInfo {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt
index d90588e..c7d9378 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt
@@ -938,6 +938,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 @Preview
 @Composable
 private fun LazyStaggeredGridDemo() {
@@ -1003,13 +1004,15 @@
                                 StaggeredGridItemSpan.FullLine
                             else
                                 StaggeredGridItemSpan.SingleLane
-                        }
+                        },
+                        key = { indices.value[it % indices.value.size] }
                     ) {
                         var expanded by remember { mutableStateOf(false) }
                         val index = indices.value[it % indices.value.size]
                         val color = colors[index]
                         Box(
                             modifier = Modifier
+                                .animateItemPlacement()
                                 .height(if (!expanded) heights[index] else heights[index] * 2)
                                 .border(2.dp, color, RoundedCornerShape(5.dp))
                                 .clickable {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnappingDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnappingDemos.kt
index e4e5e15..7b7ec83 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnappingDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnappingDemos.kt
@@ -20,6 +20,7 @@
 import androidx.compose.foundation.background
 import androidx.compose.foundation.gestures.FlingBehavior
 import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
+import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxSize
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/RowSnapLayoutInfoProvider.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/RowSnapLayoutInfoProvider.kt
index 8fccbc9..203eae5 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/RowSnapLayoutInfoProvider.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/RowSnapLayoutInfoProvider.kt
@@ -20,9 +20,11 @@
 import androidx.compose.foundation.ScrollState
 import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
 import androidx.compose.ui.unit.Density
+import kotlin.math.abs
 import kotlin.math.ceil
 import kotlin.math.floor
 import kotlin.math.roundToInt
+import kotlin.math.sign
 
 @OptIn(ExperimentalFoundationApi::class)
 fun SnapLayoutInfoProvider(
@@ -56,4 +58,31 @@
     }
 
     override fun Density.calculateApproachOffset(initialVelocity: Float): Float = 0f
+}
+
+internal fun calculateFinalOffset(velocity: Float, lowerBound: Float, upperBound: Float): Float {
+
+    fun Float.isValidDistance(): Boolean {
+        return this != Float.POSITIVE_INFINITY && this != Float.NEGATIVE_INFINITY
+    }
+
+    val finalDistance = when (sign(velocity)) {
+        0f -> {
+            if (abs(upperBound) <= abs(lowerBound)) {
+                upperBound
+            } else {
+                lowerBound
+            }
+        }
+
+        1f -> upperBound
+        -1f -> lowerBound
+        else -> 0f
+    }
+
+    return if (finalDistance.isValidDistance()) {
+        finalDistance
+    } else {
+        0f
+    }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt
index 4d8b7f9..9cb4e69 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt
@@ -35,6 +35,7 @@
 import androidx.compose.ui.composed
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.platform.InspectableValue
+import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.ExperimentalTestApi
@@ -359,19 +360,14 @@
 
     @Test
     fun draggable_callsDragStop_whenNewState() {
-        var total = 0f
         var dragStopped = 0f
-        val state = mutableStateOf(
-            DraggableState { total += it }
-        )
+        val state = mutableStateOf(DraggableState { })
         setDraggableContent {
-            if (total < 20f) {
-                Modifier.draggable(
-                    orientation = Orientation.Horizontal,
-                    onDragStopped = { dragStopped += 1 },
-                    state = state.value
-                )
-            } else Modifier
+            Modifier.draggable(
+                orientation = Orientation.Horizontal,
+                onDragStopped = { dragStopped += 1 },
+                state = state.value
+            )
         }
         rule.onNodeWithTag(draggableBoxTag).performTouchInput {
             down(center)
@@ -387,6 +383,180 @@
     }
 
     @Test
+    fun draggable_callsDragStop_whenNewOrientation() {
+        var dragStopped = 0f
+        var orientation by mutableStateOf(Orientation.Horizontal)
+        setDraggableContent {
+            Modifier.draggable(
+                orientation = orientation,
+                onDragStopped = { dragStopped += 1 },
+                onDrag = {}
+            )
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(100f, 100f))
+        }
+        rule.runOnIdle {
+            assertThat(dragStopped).isEqualTo(0f)
+            orientation = Orientation.Vertical
+        }
+        rule.runOnIdle {
+            assertThat(dragStopped).isEqualTo(1f)
+        }
+    }
+
+    @Test
+    fun draggable_callsDragStop_whenDisabled() {
+        var dragStopped = 0f
+        var enabled by mutableStateOf(true)
+        setDraggableContent {
+            Modifier.draggable(
+                orientation = Orientation.Horizontal,
+                onDragStopped = { dragStopped += 1 },
+                enabled = enabled,
+                onDrag = {}
+            )
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(100f, 100f))
+        }
+        rule.runOnIdle {
+            assertThat(dragStopped).isEqualTo(0f)
+            enabled = false
+        }
+        rule.runOnIdle {
+            assertThat(dragStopped).isEqualTo(1f)
+        }
+    }
+
+    @Test
+    fun draggable_callsDragStop_whenNewReverseDirection() {
+        var dragStopped = 0f
+        var reverseDirection by mutableStateOf(false)
+        setDraggableContent {
+            Modifier.draggable(
+                orientation = Orientation.Horizontal,
+                onDragStopped = { dragStopped += 1 },
+                onDrag = {},
+                reverseDirection = reverseDirection
+            )
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(100f, 100f))
+        }
+        rule.runOnIdle {
+            assertThat(dragStopped).isEqualTo(0f)
+            reverseDirection = true
+        }
+        rule.runOnIdle {
+            assertThat(dragStopped).isEqualTo(1f)
+        }
+    }
+
+    @Test
+    fun draggable_updates_startDragImmediately() {
+        var total = 0f
+        var startDragImmediately by mutableStateOf(false)
+        var touchSlop: Float? = null
+        setDraggableContent {
+            touchSlop = LocalViewConfiguration.current.touchSlop
+            Modifier.draggable(
+                orientation = Orientation.Horizontal,
+                onDrag = { total += it },
+                startDragImmediately = startDragImmediately
+            )
+        }
+        val delta = touchSlop!! / 2f
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(delta, 0f))
+            up()
+        }
+        rule.runOnIdle {
+            assertThat(total).isEqualTo(0f)
+            startDragImmediately = true
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(delta, 0f))
+            up()
+        }
+        rule.runOnIdle {
+            assertThat(total).isEqualTo(delta)
+        }
+    }
+
+    @Test
+    fun draggable_updates_onDragStarted() {
+        var total = 0f
+        var onDragStarted1Calls = 0
+        var onDragStarted2Calls = 0
+        var onDragStarted: (Offset) -> Unit by mutableStateOf({ onDragStarted1Calls += 1 })
+        setDraggableContent {
+            Modifier.draggable(
+                orientation = Orientation.Horizontal,
+                onDrag = { total += it },
+                onDragStarted = onDragStarted
+            )
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(100f, 100f))
+            up()
+        }
+        rule.runOnIdle {
+            assertThat(onDragStarted1Calls).isEqualTo(1)
+            assertThat(onDragStarted2Calls).isEqualTo(0)
+            onDragStarted = { onDragStarted2Calls += 1 }
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(100f, 100f))
+            up()
+        }
+        rule.runOnIdle {
+            assertThat(onDragStarted1Calls).isEqualTo(1)
+            assertThat(onDragStarted2Calls).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun draggable_updates_onDragStopped() {
+        var total = 0f
+        var onDragStopped1Calls = 0
+        var onDragStopped2Calls = 0
+        var onDragStopped: (Float) -> Unit by mutableStateOf({ onDragStopped1Calls += 1 })
+        setDraggableContent {
+            Modifier.draggable(
+                orientation = Orientation.Horizontal,
+                onDrag = { total += it },
+                onDragStopped = onDragStopped
+            )
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            down(center)
+            moveBy(Offset(100f, 100f))
+        }
+        rule.runOnIdle {
+            assertThat(onDragStopped1Calls).isEqualTo(0)
+            assertThat(onDragStopped2Calls).isEqualTo(0)
+            onDragStopped = { onDragStopped2Calls += 1 }
+        }
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            up()
+        }
+        rule.runOnIdle {
+            // We changed the lambda before we ever stopped dragging, so only the new one should be
+            // called
+            assertThat(onDragStopped1Calls).isEqualTo(0)
+            assertThat(onDragStopped2Calls).isEqualTo(1)
+        }
+    }
+
+    @Test
     fun draggable_resumesNormally_whenInterruptedWithHigherPriority() = runBlocking {
         var total = 0f
         var dragStopped = 0f
@@ -576,6 +746,112 @@
         }
     }
 
+    @Test
+    fun draggable_interactionSource_resetWhenEnabledChanged() {
+        val interactionSource = MutableInteractionSource()
+        val enabledState = mutableStateOf(true)
+
+        var scope: CoroutineScope? = null
+
+        setDraggableContent {
+            scope = rememberCoroutineScope()
+            Modifier.draggable(
+                Orientation.Horizontal,
+                enabled = enabledState.value,
+                interactionSource = interactionSource
+            ) {}
+        }
+
+        val interactions = mutableListOf<Interaction>()
+
+        scope!!.launch {
+            interactionSource.interactions.collect { interactions.add(it) }
+        }
+
+        rule.runOnIdle {
+            assertThat(interactions).isEmpty()
+        }
+
+        rule.onNodeWithTag(draggableBoxTag)
+            .performTouchInput {
+                down(Offset(visibleSize.width / 4f, visibleSize.height / 2f))
+                moveBy(Offset(visibleSize.width / 2f, 0f))
+            }
+
+        rule.runOnIdle {
+            assertThat(interactions).hasSize(1)
+            assertThat(interactions.first()).isInstanceOf(DragInteraction.Start::class.java)
+        }
+
+        rule.runOnIdle {
+            enabledState.value = false
+        }
+
+        rule.runOnIdle {
+            assertThat(interactions).hasSize(2)
+            assertThat(interactions.first()).isInstanceOf(DragInteraction.Start::class.java)
+            assertThat(interactions[1]).isInstanceOf(DragInteraction.Cancel::class.java)
+            assertThat((interactions[1] as DragInteraction.Cancel).start)
+                .isEqualTo(interactions[0])
+        }
+    }
+
+    @Test
+    fun draggable_interactionSource_resetWhenInteractionSourceChanged() {
+        val interactionSource1 = MutableInteractionSource()
+        val interactionSource2 = MutableInteractionSource()
+        val interactionSourceState = mutableStateOf(interactionSource1)
+
+        var scope: CoroutineScope? = null
+
+        setDraggableContent {
+            scope = rememberCoroutineScope()
+            Modifier.draggable(
+                Orientation.Horizontal,
+                interactionSource = interactionSourceState.value
+            ) {}
+        }
+
+        val interactions1 = mutableListOf<Interaction>()
+        val interactions2 = mutableListOf<Interaction>()
+
+        scope!!.launch {
+            interactionSource1.interactions.collect { interactions1.add(it) }
+        }
+
+        rule.runOnIdle {
+            assertThat(interactions1).isEmpty()
+            assertThat(interactions2).isEmpty()
+        }
+
+        rule.onNodeWithTag(draggableBoxTag)
+            .performTouchInput {
+                down(Offset(visibleSize.width / 4f, visibleSize.height / 2f))
+                moveBy(Offset(visibleSize.width / 2f, 0f))
+            }
+
+        rule.runOnIdle {
+            assertThat(interactions1).hasSize(1)
+            assertThat(interactions1.first()).isInstanceOf(DragInteraction.Start::class.java)
+            assertThat(interactions2).isEmpty()
+        }
+
+        rule.runOnIdle {
+            interactionSourceState.value = interactionSource2
+        }
+
+        rule.runOnIdle {
+            assertThat(interactions1).hasSize(2)
+            assertThat(interactions1.first()).isInstanceOf(DragInteraction.Start::class.java)
+            assertThat(interactions1[1]).isInstanceOf(DragInteraction.Cancel::class.java)
+            assertThat((interactions1[1] as DragInteraction.Cancel).start)
+                .isEqualTo(interactions1[0])
+            // Currently we don't emit drag start for an in progress drag, but this might change
+            // in the future.
+            assertThat(interactions2).isEmpty()
+        }
+    }
+
     @OptIn(ExperimentalTestApi::class)
     @Test
     fun draggable_cancelMidDown_shouldContinueWithNextDown() {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyGridSnapFlingBehaviorTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyGridSnapFlingBehaviorTest.kt
new file mode 100644
index 0000000..39f045c
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyGridSnapFlingBehaviorTest.kt
@@ -0,0 +1,515 @@
+/*
+ * 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.compose.foundation.gesture.snapping
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.FlingBehavior
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.snapping.MinFlingVelocityDp
+import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
+import androidx.compose.foundation.gestures.snapping.SnapPositionInLayout.Companion.CenterToCenter
+import androidx.compose.foundation.gestures.snapping.calculateDistanceToDesiredSnapPosition
+import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.grid.BaseLazyGridTestWithOrientation
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyGridState
+import androidx.compose.foundation.lazy.grid.rememberLazyGridState
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.TouchInjectionScope
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeLeft
+import androidx.compose.ui.test.swipeUp
+import androidx.compose.ui.test.swipeWithVelocity
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.unit.dp
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth
+import kotlin.math.abs
+import kotlin.math.absoluteValue
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+@OptIn(ExperimentalFoundationApi::class)
+class LazyGridSnapFlingBehaviorTest(private val orientation: Orientation) :
+    BaseLazyGridTestWithOrientation(orientation) {
+
+    private val density: Density
+        get() = rule.density
+
+    private lateinit var snapLayoutInfoProvider: SnapLayoutInfoProvider
+    private lateinit var snapFlingBehavior: FlingBehavior
+
+    @Test
+    fun belowThresholdVelocity_lessThanAnItemScroll_shouldStayInSamePage() {
+        var lazyGridState: LazyGridState? = null
+        var stepSize = 0f
+        var velocityThreshold = 0f
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState().also { lazyGridState = it }
+            stepSize = with(density) { ItemSize.toPx() }
+            velocityThreshold = with(density) { MinFlingVelocityDp.toPx() }
+            MainLayout(state = state)
+        }
+
+        // Scroll a bit
+        onMainList().swipeOnMainAxis()
+        rule.waitForIdle()
+        val currentItem = density.getCurrentSnappedItem(lazyGridState)
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(stepSize / 2, velocityThreshold / 2)
+        }
+
+        // assert
+        rule.runOnIdle {
+            val nextItem = density.getCurrentSnappedItem(lazyGridState)
+            assertEquals(currentItem, nextItem)
+        }
+    }
+
+    @Test
+    fun belowThresholdVelocity_moreThanAnItemScroll_shouldGoToNextPage() {
+        var lazyGridState: LazyGridState? = null
+        var stepSize = 0f
+        var velocityThreshold = 0f
+
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState().also { lazyGridState = it }
+            stepSize = with(density) { ItemSize.toPx() }
+            velocityThreshold = with(density) { MinFlingVelocityDp.toPx() }
+            MainLayout(state = state)
+        }
+
+        // Scroll a bit
+        onMainList().swipeOnMainAxis()
+        rule.waitForIdle()
+        val currentItem = density.getCurrentSnappedItem(lazyGridState)
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                stepSize,
+                velocityThreshold / 2
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            val nextItem = density.getCurrentSnappedItem(lazyGridState)
+            assertEquals(nextItem, currentItem + (lazyGridState?.maxCells() ?: 0))
+        }
+    }
+
+    @Test
+    fun aboveThresholdVelocityForward_notLargeEnoughScroll_shouldGoToNextPage() {
+        var lazyGridState: LazyGridState? = null
+        var stepSize = 0f
+        var velocityThreshold = 0f
+
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState().also { lazyGridState = it }
+            stepSize = with(density) { ItemSize.toPx() }
+            velocityThreshold = with(density) { MinFlingVelocityDp.toPx() }
+            MainLayout(state = state)
+        }
+
+        // Scroll a bit
+        onMainList().swipeOnMainAxis()
+        rule.waitForIdle()
+        val currentItem = density.getCurrentSnappedItem(lazyGridState)
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                stepSize / 2,
+                velocityThreshold * 2
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            val nextItem = density.getCurrentSnappedItem(lazyGridState)
+            assertEquals(nextItem, currentItem + (lazyGridState?.maxCells() ?: 0))
+        }
+    }
+
+    @Test
+    fun aboveThresholdVelocityBackward_notLargeEnoughScroll_shouldGoToPreviousPage() {
+        var lazyGridState: LazyGridState? = null
+        var stepSize = 0f
+        var velocityThreshold = 0f
+
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState().also { lazyGridState = it }
+            stepSize = with(density) { ItemSize.toPx() }
+            velocityThreshold = with(density) { MinFlingVelocityDp.toPx() }
+            MainLayout(state = state)
+        }
+
+        // Scroll a bit
+        onMainList().swipeOnMainAxis()
+        rule.waitForIdle()
+        val currentItem = density.getCurrentSnappedItem(lazyGridState)
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                stepSize / 2,
+                velocityThreshold * 2,
+                true
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            val nextItem = density.getCurrentSnappedItem(lazyGridState)
+            assertEquals(nextItem, currentItem - (lazyGridState?.maxCells() ?: 0))
+        }
+    }
+
+    @Test
+    fun aboveThresholdVelocity_largeEnoughScroll_shouldGoToNextNextPage() {
+        var lazyGridState: LazyGridState? = null
+        var stepSize = 0f
+        var velocityThreshold = 0f
+
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState().also { lazyGridState = it }
+            stepSize = with(density) { ItemSize.toPx() }
+            velocityThreshold = with(density) { MinFlingVelocityDp.toPx() }
+            MainLayout(state = state)
+        }
+
+        // Scroll a bit
+        onMainList().swipeOnMainAxis()
+        rule.waitForIdle()
+        val currentItem = density.getCurrentSnappedItem(lazyGridState)
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                1.5f * stepSize,
+                velocityThreshold * 3
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            val nextItem = density.getCurrentSnappedItem(lazyGridState)
+            assertEquals(nextItem, currentItem + 2 * (lazyGridState?.maxCells() ?: 0))
+        }
+    }
+
+    @Test
+    fun performFling_shouldPropagateVelocityIfHitEdges() {
+        var stepSize = 0f
+        var latestAvailableVelocity = Velocity.Zero
+        lateinit var lazyGridState: LazyGridState
+        val inspectingNestedScrollConnection = object : NestedScrollConnection {
+            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+                latestAvailableVelocity = available
+                return Velocity.Zero
+            }
+        }
+
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            lazyGridState = rememberLazyGridState(180) // almost at the end
+            stepSize = with(density) { ItemSize.toPx() }
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .nestedScroll(inspectingNestedScrollConnection)
+            ) {
+                MainLayout(state = lazyGridState)
+            }
+        }
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                1.5f * stepSize,
+                30000f
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            assertNotEquals(latestAvailableVelocity.toAbsoluteFloat(), 0f)
+        }
+
+        // arrange
+        rule.runOnIdle {
+            runBlocking {
+                lazyGridState.scrollToItem(20) // almost at the start
+            }
+        }
+
+        latestAvailableVelocity = Velocity.Zero
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                -1.5f * stepSize,
+                30000f
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            assertNotEquals(latestAvailableVelocity.toAbsoluteFloat(), 0f)
+        }
+    }
+
+    @Test
+    fun performFling_shouldConsumeAllVelocityIfInTheMiddleOfTheList() {
+        var stepSize = 0f
+        var latestAvailableVelocity = Velocity.Zero
+        lateinit var lazyGridState: LazyGridState
+        val inspectingNestedScrollConnection = object : NestedScrollConnection {
+            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+                latestAvailableVelocity = available
+                return Velocity.Zero
+            }
+        }
+
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            lazyGridState = rememberLazyGridState(100) // middle of the grid
+            stepSize = with(density) { ItemSize.toPx() }
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .nestedScroll(inspectingNestedScrollConnection)
+            ) {
+                MainLayout(state = lazyGridState)
+            }
+        }
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                1.5f * stepSize,
+                10000f // use a not so high velocity
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            assertEquals(latestAvailableVelocity.toAbsoluteFloat(), 0f)
+        }
+
+        // arrange
+        rule.runOnIdle {
+            runBlocking {
+                lazyGridState.scrollToItem(100) // return to the middle
+            }
+        }
+
+        latestAvailableVelocity = Velocity.Zero
+
+        // act
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                -1.5f * stepSize,
+                10000f // use a not so high velocity
+            )
+        }
+
+        // assert
+        rule.runOnIdle {
+            assertEquals(latestAvailableVelocity.toAbsoluteFloat(), 0f)
+        }
+    }
+
+    @Test
+    fun remainingScrollOffset_shouldFollowAnimationOffsets() {
+        var stepSize = 0f
+        var velocityThreshold = 0f
+        val scrollOffset = mutableListOf<Float>()
+        // arrange
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState()
+            stepSize = with(density) { ItemSize.toPx() }
+            velocityThreshold = with(density) { MinFlingVelocityDp.toPx() }
+            MainLayout(state = state, scrollOffset)
+        }
+
+        rule.mainClock.autoAdvance = false
+        // act
+        val velocity = velocityThreshold * 3
+        onMainList().performTouchInput {
+            swipeMainAxisWithVelocity(
+                1.5f * stepSize,
+                velocity
+            )
+        }
+        rule.mainClock.advanceTimeByFrame()
+
+        // assert
+        val initialTargetOffset =
+            with(snapLayoutInfoProvider) { density.calculateApproachOffset(velocity) }
+        Truth.assertThat(scrollOffset.first { it != 0f }).isWithin(0.5f)
+            .of(initialTargetOffset)
+
+        // act: wait for remaining offset to grow instead of decay, this indicates the last
+        // snap step will start
+        rule.mainClock.advanceTimeUntil {
+            scrollOffset.size > 2 &&
+                scrollOffset.last() > scrollOffset[scrollOffset.lastIndex - 1]
+        }
+
+        // assert: next calculated offset is the first value emitted by remainingScrollOffset
+        val finalRemainingOffset = with(snapLayoutInfoProvider) {
+            density.calculateSnappingOffset(10000f)
+        }
+        Truth.assertThat(scrollOffset.last()).isWithin(0.5f)
+            .of(finalRemainingOffset)
+        rule.mainClock.autoAdvance = true
+
+        // assert: value settles back to zero
+        rule.runOnIdle {
+            Truth.assertThat(scrollOffset.last()).isEqualTo(0f)
+        }
+    }
+
+    private fun onMainList() = rule.onNodeWithTag(TestTag)
+
+    @Composable
+    fun MainLayout(state: LazyGridState, scrollOffset: MutableList<Float> = mutableListOf()) {
+        snapLayoutInfoProvider = remember(state) { SnapLayoutInfoProvider(state) }
+        val innerFlingBehavior =
+            rememberSnapFlingBehavior(snapLayoutInfoProvider = snapLayoutInfoProvider)
+        snapFlingBehavior = remember(innerFlingBehavior) {
+            QuerySnapFlingBehavior(innerFlingBehavior) { scrollOffset.add(it) }
+        }
+        LazyGrid(
+            cells = GridCells.FixedSize(ItemSize),
+            state = state,
+            modifier = Modifier.testTag(TestTag),
+            flingBehavior = snapFlingBehavior
+        ) {
+            items(200) {
+                Box(modifier = Modifier
+                    .size(ItemSize)
+                    .background(Color.Yellow)) {
+                    BasicText(text = it.toString())
+                }
+            }
+        }
+    }
+
+    private fun LazyGridState.maxCells() =
+        if (layoutInfo.orientation == Orientation.Vertical) {
+            layoutInfo.visibleItemsInfo.maxOf { it.column }
+        } else {
+            layoutInfo.visibleItemsInfo.maxOf { it.row }
+        } + 1
+
+    private fun SemanticsNodeInteraction.swipeOnMainAxis() {
+        performTouchInput {
+            if (orientation == Orientation.Vertical) {
+                swipeUp()
+            } else {
+                swipeLeft()
+            }
+        }
+    }
+
+    private fun Density.getCurrentSnappedItem(state: LazyGridState?): Int {
+        var itemIndex = -1
+        if (state == null) return -1
+        var minDistance = Float.POSITIVE_INFINITY
+        (state.layoutInfo.visibleItemsInfo).forEach {
+            val distance = calculateDistanceToDesiredSnapPosition(
+                state.layoutInfo,
+                it,
+                CenterToCenter
+            )
+            if (abs(distance) < minDistance) {
+                minDistance = abs(distance)
+                itemIndex = it.index
+            }
+        }
+        return itemIndex
+    }
+
+    private fun TouchInjectionScope.swipeMainAxisWithVelocity(
+        scrollSize: Float,
+        endVelocity: Float,
+        reversed: Boolean = false
+    ) {
+        val (start, end) = if (orientation == Orientation.Vertical) {
+            bottomCenter to bottomCenter.copy(y = bottomCenter.y - scrollSize)
+        } else {
+            centerRight to centerRight.copy(x = centerRight.x - scrollSize)
+        }
+        swipeWithVelocity(
+            if (reversed) end else start,
+            if (reversed) start else end,
+            endVelocity
+        )
+    }
+
+    private fun Velocity.toAbsoluteFloat(): Float {
+        return (if (orientation == Orientation.Vertical) y else x).absoluteValue
+    }
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun params() = arrayOf(Orientation.Vertical, Orientation.Horizontal)
+
+        val ItemSize = 200.dp
+        const val TestTag = "MainList"
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyGridSnapLayoutInfoProviderTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyGridSnapLayoutInfoProviderTest.kt
new file mode 100644
index 0000000..4bbab00
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyGridSnapLayoutInfoProviderTest.kt
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2022 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.compose.foundation.gesture.snapping
+
+import androidx.compose.animation.core.calculateTargetValue
+import androidx.compose.animation.splineBasedDecay
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
+import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.grid.BaseLazyGridTestWithOrientation
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyGridState
+import androidx.compose.foundation.lazy.grid.rememberLazyGridState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.test.filters.LargeTest
+import kotlin.math.absoluteValue
+import kotlin.math.round
+import kotlin.math.sign
+import kotlin.test.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@OptIn(ExperimentalFoundationApi::class)
+@LargeTest
+@RunWith(Parameterized::class)
+class LazyGridSnapLayoutInfoProviderTest(orientation: Orientation) :
+    BaseLazyGridTestWithOrientation(orientation) {
+
+    private val density: Density get() = rule.density
+
+    @Test
+    fun snapStepSize_sameSizeItems_shouldBeAverageItemSize() {
+        var expectedItemSize = 0f
+        var actualItemSize = 0f
+
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState()
+            val layoutInfoProvider = remember(state) { createLayoutInfo(state) }.also {
+                actualItemSize = with(it) { density.calculateSnapStepSize() }
+            }
+            expectedItemSize = with(density) { FixedItemSize.toPx() }
+            MainLayout(
+                state = state,
+                layoutInfo = layoutInfoProvider,
+                items = 200,
+                itemSizeProvider = { FixedItemSize }
+            )
+        }
+
+        rule.runOnIdle {
+            assertEquals(round(expectedItemSize), round(actualItemSize))
+        }
+    }
+
+    @Test
+    fun snapStepSize_differentSizeItems_shouldBeAverageItemSizeOnReferenceIndex() {
+        var actualItemSize = 0f
+        var expectedItemSize = 0f
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState()
+            val layoutInfoProvider = remember(state) { createLayoutInfo(state) }.also {
+                actualItemSize = with(it) { density.calculateSnapStepSize() }
+            }
+            expectedItemSize = state.layoutInfo.visibleItemsInfo.filter {
+                if (vertical) {
+                    it.column == 0
+                } else {
+                    it.row == 0
+                }
+            }.map {
+                if (vertical) it.size.height else it.size.width
+            }.average().toFloat()
+
+            MainLayout(state, layoutInfoProvider, DynamicItemSizes.size, { DynamicItemSizes[it] })
+        }
+
+        rule.runOnIdle {
+            assertEquals(round(expectedItemSize), round(actualItemSize))
+        }
+    }
+
+    @Test
+    fun snapStepSize_withSpacers_shouldBeAverageItemSize() {
+        var snapStepSize = 0f
+        var actualItemSize = 0f
+        rule.setContent {
+            val density = LocalDensity.current
+            val state = rememberLazyGridState()
+            val layoutInfoProvider = remember(state) { createLayoutInfo(state) }.also {
+                snapStepSize = with(it) { density.calculateSnapStepSize() }
+            }
+
+            actualItemSize = with(density) { (FixedItemSize + FixedItemSize / 2).toPx() }
+
+            MainLayout(
+                state = state,
+                layoutInfo = layoutInfoProvider,
+                items = 200,
+                itemSizeProvider = { FixedItemSize }) {
+                if (vertical) {
+                    Column {
+                        Box(
+                            modifier = Modifier
+                                .size(FixedItemSize)
+                                .background(Color.Red)
+                        )
+                        Spacer(
+                            modifier = Modifier
+                                .size(FixedItemSize / 2)
+                                .background(Color.Yellow)
+                        )
+                    }
+                } else {
+                    Row {
+                        Box(
+                            modifier = Modifier
+                                .size(FixedItemSize)
+                                .background(Color.Red)
+                        )
+                        Spacer(
+                            modifier = Modifier
+                                .size(FixedItemSize / 2)
+                                .background(Color.Yellow)
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(round(actualItemSize), round(snapStepSize))
+        }
+    }
+
+    @Test
+    fun calculateApproachOffset_highVelocity_approachOffsetIsEqualToDecayMinusItemSize() {
+        lateinit var layoutInfoProvider: SnapLayoutInfoProvider
+        val decay = splineBasedDecay<Float>(rule.density)
+        fun calculateTargetOffset(velocity: Float): Float {
+            val offset = decay.calculateTargetValue(0f, velocity).absoluteValue
+            return (offset - with(density) { 200.dp.toPx() }).coerceAtLeast(0f) * velocity.sign
+        }
+        rule.setContent {
+            val state = rememberLazyGridState()
+            layoutInfoProvider = remember(state) { createLayoutInfo(state) }
+            LazyGrid(
+                cells = GridCells.Fixed(3),
+                state = state,
+                flingBehavior = rememberSnapFlingBehavior(layoutInfoProvider)
+            ) {
+                items(200) {
+                    Box(modifier = Modifier.size(200.dp))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(
+                with(layoutInfoProvider) { density.calculateApproachOffset(10000f) },
+                calculateTargetOffset(10000f)
+            )
+            assertEquals(
+                with(layoutInfoProvider) { density.calculateApproachOffset(-10000f) },
+                calculateTargetOffset(-10000f)
+            )
+        }
+    }
+
+    @Test
+    fun calculateApproachOffset_lowVelocity_approachOffsetIsEqualToZero() {
+        lateinit var layoutInfoProvider: SnapLayoutInfoProvider
+        rule.setContent {
+            val state = rememberLazyGridState()
+            layoutInfoProvider = remember(state) { createLayoutInfo(state) }
+            LazyGrid(
+                cells = GridCells.Fixed(3),
+                state = state,
+                flingBehavior = rememberSnapFlingBehavior(layoutInfoProvider)
+            ) {
+                items(200) {
+                    Box(modifier = Modifier.size(200.dp))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(
+                with(layoutInfoProvider) { density.calculateApproachOffset(1000f) },
+                0f
+            )
+            assertEquals(
+                with(layoutInfoProvider) { density.calculateApproachOffset(-1000f) },
+                0f
+            )
+        }
+    }
+
+    @Composable
+    private fun MainLayout(
+        state: LazyGridState,
+        layoutInfo: SnapLayoutInfoProvider,
+        items: Int,
+        itemSizeProvider: (Int) -> Dp,
+        gridItem: @Composable (Int) -> Unit = { Box(Modifier.size(itemSizeProvider(it))) }
+    ) {
+        LazyGrid(
+            cells = GridCells.Fixed(3),
+            state = state,
+            flingBehavior = rememberSnapFlingBehavior(snapLayoutInfoProvider = layoutInfo)
+        ) {
+            items(items) { gridItem(it) }
+        }
+    }
+
+    private fun createLayoutInfo(
+        state: LazyGridState,
+    ): SnapLayoutInfoProvider {
+        return SnapLayoutInfoProvider(state)
+    }
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun params() = arrayOf(Orientation.Vertical, Orientation.Horizontal)
+
+        val FixedItemSize = 200.dp
+        val DynamicItemSizes = (200..500).map { it.dp }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyListSnapFlingBehaviorTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyListSnapFlingBehaviorTest.kt
index 784b4c9..3153d92 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyListSnapFlingBehaviorTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/gesture/snapping/LazyListSnapFlingBehaviorTest.kt
@@ -23,6 +23,7 @@
 import androidx.compose.foundation.gestures.snapping.MinFlingVelocityDp
 import androidx.compose.foundation.gestures.snapping.SnapFlingBehavior
 import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
+import androidx.compose.foundation.gestures.snapping.SnapPositionInLayout.Companion.CenterToCenter
 import androidx.compose.foundation.gestures.snapping.calculateDistanceToDesiredSnapPosition
 import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
 import androidx.compose.foundation.layout.Box
@@ -498,13 +499,11 @@
 
         val ItemSize = 200.dp
         const val TestTag = "MainList"
-        val CenterToCenter: Density.(Float, Float) -> Float =
-            { layoutSize, itemSize -> layoutSize / 2f - itemSize / 2f }
     }
 }
 
 @OptIn(ExperimentalFoundationApi::class)
-private class QuerySnapFlingBehavior(
+internal class QuerySnapFlingBehavior(
     val snapFlingBehavior: SnapFlingBehavior,
     val onAnimationStep: (Float) -> Unit
 ) : FlingBehavior {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
index 61ce9f7..030e1d7 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
@@ -760,7 +760,7 @@
             rule.onNodeWithTag("4").assertDoesNotExist()
             rule.onNodeWithTag("5").assertDoesNotExist()
             val item2Size = itemSize3 /* the real size of the item 2 */
-            // item 2 moves from and item 4 moves to `0 - item size`, right before the start edge
+            // item 2 moves from `0 - item size`, right before the start edge
             val startItem2Offset = -item2Size
             val item2Offset =
                 startItem2Offset + (itemSize2 - startItem2Offset) * fraction
@@ -833,7 +833,7 @@
         }
 
         onAnimationFrame { fraction ->
-            // item 1 moves from and item 8 moves to `gridSize`, right after the end edge
+            // item 8 moves from and item 2 moves to `gridSize`, right after the end edge
             val startItem8Offset = gridSize
             val endItem2Offset = gridSize
             val line4Size = itemSize3
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyScrollTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyScrollTest.kt
index 3bf22a4..c868e03 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyScrollTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyScrollTest.kt
@@ -19,6 +19,7 @@
 import androidx.compose.animation.core.FloatSpringSpec
 import androidx.compose.foundation.AutoTestFrameClock
 import androidx.compose.foundation.gestures.animateScrollBy
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.width
@@ -65,22 +66,28 @@
             itemSizeDp = itemSizePx.toDp()
             containerSizeDp = itemSizeDp * 3
         }
+    }
+
+    private fun testScroll(spacingPx: Int = 0, assertBlock: suspend () -> Unit) {
         rule.setContent {
             state = rememberLazyGridState()
             scope = rememberCoroutineScope()
-            TestContent()
+            TestContent(with(rule.density) { spacingPx.toDp() })
+        }
+        runBlocking {
+            assertBlock()
         }
     }
 
     @Test
-    fun setupWorks() {
+    fun setupWorks() = testScroll {
         assertThat(state.firstVisibleItemIndex).isEqualTo(0)
         assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
         assertThat(state.firstVisibleItemIndex).isEqualTo(0)
     }
 
     @Test
-    fun scrollToItem() = runBlocking {
+    fun scrollToItem() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(2)
         }
@@ -95,7 +102,7 @@
     }
 
     @Test
-    fun scrollToItemWithOffset() = runBlocking {
+    fun scrollToItemWithOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(6, 10)
         }
@@ -104,7 +111,7 @@
     }
 
     @Test
-    fun scrollToItemWithNegativeOffset() = runBlocking {
+    fun scrollToItemWithNegativeOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(6, -10)
         }
@@ -114,7 +121,7 @@
     }
 
     @Test
-    fun scrollToItemWithPositiveOffsetLargerThanAvailableSize() = runBlocking {
+    fun scrollToItemWithPositiveOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(itemsCount - 6, 10)
         }
@@ -123,7 +130,7 @@
     }
 
     @Test
-    fun scrollToItemWithNegativeOffsetLargerThanAvailableSize() = runBlocking {
+    fun scrollToItemWithNegativeOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(1, -(itemSizePx + 10))
         }
@@ -132,7 +139,7 @@
     }
 
     @Test
-    fun scrollToItemWithIndexLargerThanItemsCount() = runBlocking {
+    fun scrollToItemWithIndexLargerThanItemsCount() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(itemsCount + 4)
         }
@@ -140,7 +147,7 @@
     }
 
     @Test
-    fun animateScrollBy() = runBlocking {
+    fun animateScrollBy() = testScroll {
         val scrollDistance = 320
 
         val expectedLine = scrollDistance / itemSizePx // resolves to 3
@@ -155,7 +162,7 @@
     }
 
     @Test
-    fun animateScrollToItem() = runBlocking {
+    fun animateScrollToItem() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(10, 10)
         }
@@ -164,7 +171,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithOffset() = runBlocking {
+    fun animateScrollToItemWithOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(6, 10)
         }
@@ -173,7 +180,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithNegativeOffset() = runBlocking {
+    fun animateScrollToItemWithNegativeOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(6, -10)
         }
@@ -183,7 +190,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithPositiveOffsetLargerThanAvailableSize() = runBlocking {
+    fun animateScrollToItemWithPositiveOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(itemsCount - 6, 10)
         }
@@ -192,7 +199,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithNegativeOffsetLargerThanAvailableSize() = runBlocking {
+    fun animateScrollToItemWithNegativeOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(2, -(itemSizePx + 10))
         }
@@ -201,7 +208,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithIndexLargerThanItemsCount() = runBlocking {
+    fun animateScrollToItemWithIndexLargerThanItemsCount() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(itemsCount + 2)
         }
@@ -209,42 +216,42 @@
     }
 
     @Test
-    fun animatePerFrameForwardToVisibleItem() {
+    fun animatePerFrameForwardToVisibleItem() = testScroll {
         assertSpringAnimation(toIndex = 4)
     }
 
     @Test
-    fun animatePerFrameForwardToVisibleItemWithOffset() {
+    fun animatePerFrameForwardToVisibleItemWithOffset() = testScroll {
         assertSpringAnimation(toIndex = 4, toOffset = 35)
     }
 
     @Test
-    fun animatePerFrameForwardToNotVisibleItem() {
+    fun animatePerFrameForwardToNotVisibleItem() = testScroll {
         assertSpringAnimation(toIndex = 16)
     }
 
     @Test
-    fun animatePerFrameForwardToNotVisibleItemWithOffset() {
+    fun animatePerFrameForwardToNotVisibleItemWithOffset() = testScroll {
         assertSpringAnimation(toIndex = 20, toOffset = 35)
     }
 
     @Test
-    fun animatePerFrameBackward() {
+    fun animatePerFrameBackward() = testScroll {
         assertSpringAnimation(toIndex = 2, fromIndex = 12)
     }
 
     @Test
-    fun animatePerFrameBackwardWithOffset() {
+    fun animatePerFrameBackwardWithOffset() = testScroll {
         assertSpringAnimation(toIndex = 2, fromIndex = 10, fromOffset = 58)
     }
 
     @Test
-    fun animatePerFrameBackwardWithInitialOffset() {
+    fun animatePerFrameBackwardWithInitialOffset() = testScroll {
         assertSpringAnimation(toIndex = 0, toOffset = 40, fromIndex = 8)
     }
 
     @Test
-    fun animateScrollToItemWithOffsetLargerThanItemSize_forward() = runBlocking {
+    fun animateScrollToItemWithOffsetLargerThanItemSize_forward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(10, -itemSizePx * 3)
         }
@@ -253,7 +260,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithOffsetLargerThanItemSize_backward() = runBlocking {
+    fun animateScrollToItemWithOffsetLargerThanItemSize_backward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(10)
             state.animateScrollToItem(0, itemSizePx * 3)
@@ -263,14 +270,14 @@
     }
 
     @Test
-    fun canScrollForward() = runBlocking {
+    fun canScrollForward() = testScroll {
         assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
         assertThat(state.canScrollForward).isTrue()
         assertThat(state.canScrollBackward).isFalse()
     }
 
     @Test
-    fun canScrollBackward() = runBlocking {
+    fun canScrollBackward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(itemsCount)
         }
@@ -280,7 +287,7 @@
     }
 
     @Test
-    fun canScrollForwardAndBackward() = runBlocking {
+    fun canScrollForwardAndBackward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(10)
         }
@@ -289,11 +296,32 @@
         assertThat(state.canScrollBackward).isTrue()
     }
 
+    @Test
+    fun animatePerFrameForwardWithSpacing() = testScroll(spacingPx = 10) {
+        assertSpringAnimation(toIndex = 16, spacingPx = 10)
+    }
+
+    @Test
+    fun animatePerFrameForwardWithNegativeSpacing() = testScroll(spacingPx = -10) {
+        assertSpringAnimation(toIndex = 16, spacingPx = -10)
+    }
+
+    @Test
+    fun animatePerFrameBackwardWithSpacing() = testScroll(spacingPx = 10) {
+        assertSpringAnimation(toIndex = 2, fromIndex = 12, spacingPx = 10)
+    }
+
+    @Test
+    fun animatePerFrameBackwardWithNegativeSpacing() = testScroll(spacingPx = -10) {
+        assertSpringAnimation(toIndex = 2, fromIndex = 12, spacingPx = -10)
+    }
+
     private fun assertSpringAnimation(
         toIndex: Int,
         toOffset: Int = 0,
         fromIndex: Int = 0,
-        fromOffset: Int = 0
+        fromOffset: Int = 0,
+        spacingPx: Int = 0
     ) {
         if (fromIndex != 0 || fromOffset != 0) {
             rule.runOnIdle {
@@ -317,8 +345,9 @@
             Thread.sleep(5)
         }
 
-        val startOffset = (fromIndex / 2 * itemSizePx + fromOffset).toFloat()
-        val endOffset = (toIndex / 2 * itemSizePx + toOffset).toFloat()
+        val itemWSpacing = itemSizePx + spacingPx
+        val startOffset = (fromIndex / 2 * itemWSpacing + fromOffset).toFloat()
+        val endOffset = (toIndex / 2 * itemWSpacing + toOffset).toFloat()
         val spec = FloatSpringSpec()
 
         val duration =
@@ -330,7 +359,7 @@
             val expectedValue =
                 spec.getValueFromNanos(nanosTime, startOffset, endOffset, 0f)
             val actualValue =
-                (state.firstVisibleItemIndex / 2 * itemSizePx + state.firstVisibleItemScrollOffset)
+                state.firstVisibleItemIndex / 2 * itemWSpacing + state.firstVisibleItemScrollOffset
             assertWithMessage(
                 "On animation frame at $i index=${state.firstVisibleItemIndex} " +
                     "offset=${state.firstVisibleItemScrollOffset} expectedValue=$expectedValue"
@@ -346,9 +375,14 @@
     }
 
     @Composable
-    private fun TestContent() {
+    private fun TestContent(spacingDp: Dp) {
         if (vertical) {
-            LazyVerticalGrid(GridCells.Fixed(2), Modifier.height(containerSizeDp), state) {
+            LazyVerticalGrid(
+                GridCells.Fixed(2),
+                Modifier.height(containerSizeDp),
+                state,
+                verticalArrangement = Arrangement.spacedBy(spacingDp)
+            ) {
                 items(itemsCount) {
                     ItemContent()
                 }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt
index 8d2a237..bca1dc3 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt
@@ -26,6 +26,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.foundation.lazy.LazyRow
@@ -73,21 +74,27 @@
             itemSizeDp = itemSizePx.toDp()
             containerSizeDp = itemSizeDp * 3
         }
+    }
+
+    private fun testScroll(spacingPx: Int = 0, assertBlock: suspend () -> Unit) {
         rule.setContent {
             state = rememberLazyListState()
             scope = rememberCoroutineScope()
-            TestContent()
+            TestContent(with(rule.density) { spacingPx.toDp() })
+        }
+        runBlocking {
+            assertBlock()
         }
     }
 
     @Test
-    fun setupWorks() {
+    fun setupWorks() = testScroll {
         assertThat(state.firstVisibleItemIndex).isEqualTo(0)
         assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
     }
 
     @Test
-    fun scrollToItem() = runBlocking {
+    fun scrollToItem() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(3)
         }
@@ -96,7 +103,7 @@
     }
 
     @Test
-    fun scrollToItemWithOffset() = runBlocking {
+    fun scrollToItemWithOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(3, 10)
         }
@@ -105,7 +112,7 @@
     }
 
     @Test
-    fun scrollToItemWithNegativeOffset() = runBlocking {
+    fun scrollToItemWithNegativeOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(3, -10)
         }
@@ -115,7 +122,7 @@
     }
 
     @Test
-    fun scrollToItemWithPositiveOffsetLargerThanAvailableSize() = runBlocking {
+    fun scrollToItemWithPositiveOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(itemsCount - 3, 10)
         }
@@ -124,7 +131,7 @@
     }
 
     @Test
-    fun scrollToItemWithNegativeOffsetLargerThanAvailableSize() = runBlocking {
+    fun scrollToItemWithNegativeOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(1, -(itemSizePx + 10))
         }
@@ -133,7 +140,7 @@
     }
 
     @Test
-    fun scrollToItemWithIndexLargerThanItemsCount() = runBlocking {
+    fun scrollToItemWithIndexLargerThanItemsCount() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(itemsCount + 2)
         }
@@ -141,7 +148,7 @@
     }
 
     @Test
-    fun animateScrollBy() = runBlocking {
+    fun animateScrollBy() = testScroll {
         val scrollDistance = 320
 
         val expectedIndex = scrollDistance / itemSizePx // resolves to 3
@@ -155,7 +162,7 @@
     }
 
     @Test
-    fun animateScrollToItem() = runBlocking {
+    fun animateScrollToItem() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(5, 10)
         }
@@ -164,7 +171,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithOffset() = runBlocking {
+    fun animateScrollToItemWithOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(3, 10)
         }
@@ -173,7 +180,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithNegativeOffset() = runBlocking {
+    fun animateScrollToItemWithNegativeOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(3, -10)
         }
@@ -183,7 +190,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithPositiveOffsetLargerThanAvailableSize() = runBlocking {
+    fun animateScrollToItemWithPositiveOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(itemsCount - 3, 10)
         }
@@ -192,7 +199,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithNegativeOffsetLargerThanAvailableSize() = runBlocking {
+    fun animateScrollToItemWithNegativeOffsetLargerThanAvailableSize() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(1, -(itemSizePx + 10))
         }
@@ -201,7 +208,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithIndexLargerThanItemsCount() = runBlocking {
+    fun animateScrollToItemWithIndexLargerThanItemsCount() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(itemsCount + 2)
         }
@@ -209,42 +216,42 @@
     }
 
     @Test
-    fun animatePerFrameForwardToVisibleItem() {
+    fun animatePerFrameForwardToVisibleItem() = testScroll {
         assertSpringAnimation(toIndex = 2)
     }
 
     @Test
-    fun animatePerFrameForwardToVisibleItemWithOffset() {
+    fun animatePerFrameForwardToVisibleItemWithOffset() = testScroll {
         assertSpringAnimation(toIndex = 2, toOffset = 35)
     }
 
     @Test
-    fun animatePerFrameForwardToNotVisibleItem() {
+    fun animatePerFrameForwardToNotVisibleItem() = testScroll {
         assertSpringAnimation(toIndex = 8)
     }
 
     @Test
-    fun animatePerFrameForwardToNotVisibleItemWithOffset() {
+    fun animatePerFrameForwardToNotVisibleItemWithOffset() = testScroll {
         assertSpringAnimation(toIndex = 10, toOffset = 35)
     }
 
     @Test
-    fun animatePerFrameBackward() {
+    fun animatePerFrameBackward() = testScroll {
         assertSpringAnimation(toIndex = 1, fromIndex = 6)
     }
 
     @Test
-    fun animatePerFrameBackwardWithOffset() {
+    fun animatePerFrameBackwardWithOffset() = testScroll {
         assertSpringAnimation(toIndex = 1, fromIndex = 5, fromOffset = 58)
     }
 
     @Test
-    fun animatePerFrameBackwardWithInitialOffset() {
+    fun animatePerFrameBackwardWithInitialOffset() = testScroll {
         assertSpringAnimation(toIndex = 0, toOffset = 20, fromIndex = 8)
     }
 
     @Test
-    fun animateScrollToItemWithOffsetLargerThanItemSize_forward() = runBlocking {
+    fun animateScrollToItemWithOffsetLargerThanItemSize_forward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(10, -itemSizePx * 3)
         }
@@ -253,7 +260,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithOffsetLargerThanItemSize_backward() = runBlocking {
+    fun animateScrollToItemWithOffsetLargerThanItemSize_backward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(10)
             state.animateScrollToItem(0, itemSizePx * 3)
@@ -263,14 +270,14 @@
     }
 
     @Test
-    fun canScrollForward() = runBlocking {
+    fun canScrollForward() = testScroll {
         assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
         assertThat(state.canScrollForward).isTrue()
         assertThat(state.canScrollBackward).isFalse()
     }
 
     @Test
-    fun canScrollBackward() = runBlocking {
+    fun canScrollBackward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(itemsCount)
         }
@@ -280,7 +287,7 @@
     }
 
     @Test
-    fun canScrollForwardAndBackward() = runBlocking {
+    fun canScrollForwardAndBackward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(1)
         }
@@ -289,11 +296,32 @@
         assertThat(state.canScrollBackward).isTrue()
     }
 
+    @Test
+    fun animatePerFrameWithSpacing() = testScroll(spacingPx = 10) {
+        assertSpringAnimation(toIndex = 8, spacingPx = 10)
+    }
+
+    @Test
+    fun animatePerFrameWithNegativeSpacing() = testScroll(spacingPx = -10) {
+        assertSpringAnimation(toIndex = 8, spacingPx = -10)
+    }
+
+    @Test
+    fun animatePerFrameBackwardWithSpacing() = testScroll(spacingPx = 10) {
+        assertSpringAnimation(toIndex = 1, fromIndex = 6, spacingPx = 10)
+    }
+
+    @Test
+    fun animatePerFrameBackwardWithNegativeSpacing() = testScroll(spacingPx = -10) {
+        assertSpringAnimation(toIndex = 1, fromIndex = 6, spacingPx = -10)
+    }
+
     private fun assertSpringAnimation(
         toIndex: Int,
         toOffset: Int = 0,
         fromIndex: Int = 0,
-        fromOffset: Int = 0
+        fromOffset: Int = 0,
+        spacingPx: Int = 0
     ) {
         if (fromIndex != 0 || fromOffset != 0) {
             rule.runOnIdle {
@@ -317,8 +345,9 @@
             Thread.sleep(5)
         }
 
-        val startOffset = (fromIndex * itemSizePx + fromOffset).toFloat()
-        val endOffset = (toIndex * itemSizePx + toOffset).toFloat()
+        val itemSizeWSpacing = itemSizePx + spacingPx
+        val startOffset = (fromIndex * itemSizeWSpacing + fromOffset).toFloat()
+        val endOffset = (toIndex * itemSizeWSpacing + toOffset).toFloat()
         val spec = FloatSpringSpec()
 
         val duration =
@@ -329,8 +358,9 @@
             val nanosTime = TimeUnit.MILLISECONDS.toNanos(i)
             val expectedValue =
                 spec.getValueFromNanos(nanosTime, startOffset, endOffset, 0f)
-            val actualValue =
-                (state.firstVisibleItemIndex * itemSizePx + state.firstVisibleItemScrollOffset)
+            val actualValue = (
+                state.firstVisibleItemIndex * itemSizeWSpacing + state.firstVisibleItemScrollOffset
+                )
             assertWithMessage(
                 "On animation frame at $i index=${state.firstVisibleItemIndex} " +
                     "offset=${state.firstVisibleItemScrollOffset} expectedValue=$expectedValue"
@@ -346,15 +376,22 @@
     }
 
     @Composable
-    private fun TestContent() {
+    private fun TestContent(spacingDp: Dp) {
         if (vertical) {
-            LazyColumn(Modifier.height(containerSizeDp), state) {
+            LazyColumn(
+                Modifier.height(containerSizeDp),
+                state,
+                verticalArrangement = Arrangement.spacedBy(spacingDp)
+            ) {
                 items(itemsCount) {
                     ItemContent()
                 }
             }
         } else {
-            LazyRow(Modifier.width(containerSizeDp), state) {
+            LazyRow(
+                Modifier.width(containerSizeDp), state,
+                horizontalArrangement = Arrangement.spacedBy(spacingDp)
+            ) {
                 items(itemsCount) {
                     ItemContent()
                 }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateItemPlacementTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateItemPlacementTest.kt
new file mode 100644
index 0000000..984c7d4
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateItemPlacementTest.kt
@@ -0,0 +1,2181 @@
+/*
+ * 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.compose.foundation.lazy.staggeredgrid
+
+import androidx.compose.animation.core.FiniteAnimationSpec
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.gestures.scrollBy
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.requiredHeight
+import androidx.compose.foundation.layout.requiredHeightIn
+import androidx.compose.foundation.layout.requiredWidth
+import androidx.compose.foundation.layout.requiredWidthIn
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assertHeightIsEqualTo
+import androidx.compose.ui.test.assertIsNotDisplayed
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntRect
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.round
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import kotlin.math.roundToInt
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@OptIn(ExperimentalFoundationApi::class)
+@LargeTest
+@RunWith(Parameterized::class)
+class LazyStaggeredGridAnimateItemPlacementTest(private val config: Config) {
+
+    private val isVertical: Boolean get() = config.isVertical
+    private val reverseLayout: Boolean get() = config.reverseLayout
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    // the numbers should be divisible by 8 to avoid the rounding issues as we run 4 or 8 frames
+    // of the animation.
+    private val itemSize: Float = 40f
+    private var itemSizeDp: Dp = Dp.Infinity
+    private val itemSize2: Float = 24f
+    private var itemSize2Dp: Dp = Dp.Infinity
+    private val itemSize3: Float = 16f
+    private var itemSize3Dp: Dp = Dp.Infinity
+    private val containerSize: Float = itemSize * 5
+    private var containerSizeDp: Dp = Dp.Infinity
+    private val spacing: Float = 8f
+    private var spacingDp: Dp = Dp.Infinity
+    private val itemSizePlusSpacing = itemSize + spacing
+    private var itemSizePlusSpacingDp = Dp.Infinity
+    private lateinit var state: LazyStaggeredGridState
+
+    @Before
+    fun before() {
+        rule.mainClock.autoAdvance = false
+        with(rule.density) {
+            itemSizeDp = itemSize.toDp()
+            itemSize2Dp = itemSize2.toDp()
+            itemSize3Dp = itemSize3.toDp()
+            containerSizeDp = containerSize.toDp()
+            spacingDp = spacing.toDp()
+            itemSizePlusSpacingDp = itemSizePlusSpacing.toDp()
+        }
+    }
+
+    @Test
+    fun reorderTwoItems() {
+        var list by mutableStateOf(listOf(0, 1))
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(1, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0f + itemSize * fraction),
+                1 to AxisOffset(0f, itemSize - itemSize * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun reorderTwoByTwoItems() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3))
+        rule.setContent {
+            LazyStaggeredGrid(2) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(3, 2, 1, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            val increasing = 0 + itemSize * fraction
+            val decreasing = itemSize - itemSize * fraction
+            assertPositions(
+                0 to AxisOffset(increasing, increasing),
+                1 to AxisOffset(decreasing, increasing),
+                2 to AxisOffset(increasing, decreasing),
+                3 to AxisOffset(decreasing, decreasing),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun reorderTwoItems_layoutInfoHasFinalPositions() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3))
+        rule.setContent {
+            LazyStaggeredGrid(2) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertLayoutInfoPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(3, 2, 1, 0)
+        }
+
+        onAnimationFrame {
+            // fraction doesn't affect the offsets in layout info
+            assertLayoutInfoPositions(
+                3 to AxisOffset(0f, 0f),
+                2 to AxisOffset(itemSize, 0f),
+                1 to AxisOffset(0f, itemSize),
+                0 to AxisOffset(itemSize, itemSize)
+            )
+        }
+    }
+
+    @Test
+    fun reorderFirstAndLastItems() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, itemSize),
+            2 to AxisOffset(0f, itemSize * 2),
+            3 to AxisOffset(0f, itemSize * 3),
+            4 to AxisOffset(0f, itemSize * 4)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(4, 1, 2, 3, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0f + itemSize * 4 * fraction),
+                1 to AxisOffset(0f, itemSize),
+                2 to AxisOffset(0f, itemSize * 2),
+                3 to AxisOffset(0f, itemSize * 3),
+                4 to AxisOffset(0f, itemSize * 4 - itemSize * 4 * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveFirstItemToEndCausingAllItemsToAnimate() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5))
+        rule.setContent {
+            LazyStaggeredGrid(2) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize),
+            4 to AxisOffset(0f, itemSize * 2),
+            5 to AxisOffset(itemSize, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(1, 2, 3, 4, 5, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            val increasingX = 0 + itemSize * fraction
+            val decreasingX = itemSize - itemSize * fraction
+            assertPositions(
+                0 to AxisOffset(increasingX, 0f + itemSize * 2 * fraction),
+                1 to AxisOffset(decreasingX, 0f),
+                2 to AxisOffset(increasingX, itemSize - itemSize * fraction),
+                3 to AxisOffset(decreasingX, itemSize),
+                4 to AxisOffset(increasingX, itemSize * 2 - itemSize * fraction),
+                5 to AxisOffset(decreasingX, itemSize * 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun itemSizeChangeAnimatesNextItems() {
+        var size by mutableStateOf(itemSizeDp)
+        rule.setContent {
+            LazyStaggeredGrid(1, minSize = itemSizeDp * 5, maxSize = itemSizeDp * 5) {
+                items(listOf(0, 1, 2, 3), key = { it }) {
+                    Item(it, size = if (it == 1) size else itemSizeDp)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            size = itemSizeDp * 2
+        }
+        rule.mainClock.advanceTimeByFrame()
+
+        rule.onNodeWithTag("1")
+            .assertMainAxisSizeIsEqualTo(size)
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0f),
+                1 to AxisOffset(0f, itemSize),
+                2 to AxisOffset(0f, itemSize * 2 + itemSize * fraction),
+                3 to AxisOffset(0f, itemSize * 3 + itemSize * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun onlyItemsWithModifierAnimates() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    Item(it, animSpec = if (it == 1 || it == 3) AnimSpec else null)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(1, 2, 3, 4, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, itemSize * 4),
+                1 to AxisOffset(0f, itemSize - itemSize * fraction),
+                2 to AxisOffset(0f, itemSize),
+                3 to AxisOffset(0f, itemSize * 3 - itemSize * fraction),
+                4 to AxisOffset(0f, itemSize * 3),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun animationsWithDifferentDurations() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    val duration = if (it == 1 || it == 3) Duration * 2 else Duration
+                    Item(it, animSpec = tween(duration.toInt(), easing = LinearEasing))
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(1, 2, 3, 4, 0)
+        }
+
+        onAnimationFrame(duration = Duration * 2) { fraction ->
+            val shorterAnimFraction = (fraction * 2).coerceAtMost(1f)
+            assertPositions(
+                0 to AxisOffset(0f, 0 + itemSize * 4 * shorterAnimFraction),
+                1 to AxisOffset(0f, itemSize - itemSize * fraction),
+                2 to AxisOffset(0f, itemSize * 2 - itemSize * shorterAnimFraction),
+                3 to AxisOffset(0f, itemSize * 3 - itemSize * fraction),
+                4 to AxisOffset(0f, itemSize * 4 - itemSize * shorterAnimFraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun multipleChildrenPerItem() {
+        var list by mutableStateOf(listOf(0, 2))
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    Item(it)
+                    Item(it + 1)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(0f, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(2, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0 + itemSize * fraction),
+                1 to AxisOffset(0f, 0 + itemSize * fraction),
+                2 to AxisOffset(0f, itemSize - itemSize * fraction),
+                3 to AxisOffset(0f, itemSize - itemSize * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun multipleChildrenPerItemSomeDoNotAnimate() {
+        var list by mutableStateOf(listOf(0, 2))
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    Item(it)
+                    Item(it + 1, animSpec = null)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(2, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0 + itemSize * fraction),
+                1 to AxisOffset(0f, itemSize),
+                2 to AxisOffset(0f, itemSize - itemSize * fraction),
+                3 to AxisOffset(0f, 0f),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun animateSpacingChange() {
+        var currentSpacing by mutableStateOf(0.dp)
+        rule.setContent {
+            LazyStaggeredGrid(
+                1,
+                spacing = currentSpacing
+            ) {
+                items(listOf(0, 1), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, itemSize),
+        )
+
+        rule.runOnUiThread {
+            currentSpacing = spacingDp
+        }
+        rule.mainClock.advanceTimeByFrame()
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0f),
+                1 to AxisOffset(0f, itemSize + spacing * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToTheBottomOutsideOfBounds() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11))
+        val gridSize = itemSize * 3
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize),
+            4 to AxisOffset(0f, itemSize * 2),
+            5 to AxisOffset(itemSize, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 8, 2, 3, 4, 5, 6, 7, 1, 9, 10, 11)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 1 moves to and item 8 moves from `gridSize`, right after the end edge
+            val item1Offset = AxisOffset(itemSize, 0 + gridSize * fraction)
+            val item8Offset =
+                AxisOffset(itemSize, gridSize - gridSize * fraction)
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                if (item1Offset.mainAxis < itemSize * 3) {
+                    add(1 to item1Offset)
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                add(2 to AxisOffset(0f, itemSize))
+                add(3 to AxisOffset(itemSize, itemSize))
+                add(4 to AxisOffset(0f, itemSize * 2))
+                add(5 to AxisOffset(itemSize, itemSize * 2))
+                if (item8Offset.mainAxis < itemSize * 3) {
+                    add(8 to item8Offset)
+                } else {
+                    rule.onNodeWithTag("8").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToTheTopOutsideOfBounds() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11))
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = itemSizeDp * 3, startIndex = 6) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            6 to AxisOffset(0f, 0f),
+            7 to AxisOffset(itemSize, 0f),
+            8 to AxisOffset(0f, itemSize),
+            9 to AxisOffset(itemSize, itemSize),
+            10 to AxisOffset(0f, itemSize * 2),
+            11 to AxisOffset(itemSize, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 8, 2, 3, 4, 5, 6, 7, 1, 9, 10, 11)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 1 moves from and item 8 moves to `0 - itemSize`, right before the start edge
+            val item8Offset = AxisOffset(0f, itemSize - itemSize * 2 * fraction)
+            val item1Offset = AxisOffset(0f, -itemSize + itemSize * 2 * fraction)
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                if (item1Offset.mainAxis > -itemSize) {
+                    add(1 to item1Offset)
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                add(6 to AxisOffset(0f, 0f))
+                add(7 to AxisOffset(itemSize, 0f))
+                if (item8Offset.mainAxis > -itemSize) {
+                    add(8 to item8Offset)
+                } else {
+                    rule.onNodeWithTag("8").assertIsNotDisplayed()
+                }
+                add(9 to AxisOffset(itemSize, itemSize))
+                add(10 to AxisOffset(0f, itemSize * 2))
+                add(11 to AxisOffset(itemSize, itemSize * 2))
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveFirstItemToEndCausingAllItemsToAnimate_withSpacing() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7))
+        rule.setContent {
+            LazyStaggeredGrid(2, spacing = spacingDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(1, 2, 3, 4, 5, 6, 7, 0)
+        }
+
+        onAnimationFrame { fraction ->
+            val increasingX = fraction * itemSize
+            val decreasingX = itemSize - itemSize * fraction
+            assertPositions(
+                0 to AxisOffset(increasingX, itemSizePlusSpacing * 3 * fraction),
+                1 to AxisOffset(decreasingX, 0f),
+                2 to AxisOffset(
+                    increasingX,
+                    itemSizePlusSpacing - itemSizePlusSpacing * fraction
+                ),
+                3 to AxisOffset(decreasingX, itemSizePlusSpacing),
+                4 to AxisOffset(
+                    increasingX,
+                    itemSizePlusSpacing * 2 - itemSizePlusSpacing * fraction
+                ),
+                5 to AxisOffset(decreasingX, itemSizePlusSpacing * 2),
+                6 to AxisOffset(
+                    increasingX,
+                    itemSizePlusSpacing * 3 - itemSizePlusSpacing * fraction
+                ),
+                7 to AxisOffset(decreasingX, itemSizePlusSpacing * 3),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToTheBottomOutsideOfBounds_withSpacing() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
+        val gridSize = itemSize * 3 + spacing * 2
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(
+                2,
+                maxSize = gridSizeDp,
+                spacing = spacingDp
+            ) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSizePlusSpacing),
+            3 to AxisOffset(itemSize, itemSizePlusSpacing),
+            4 to AxisOffset(0f, itemSizePlusSpacing * 2),
+            5 to AxisOffset(itemSize, itemSizePlusSpacing * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 8, 2, 3, 4, 5, 6, 7, 1, 9)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 1 moves to and item 8 moves from `gridSize`, right after the end edge
+            val item1Offset = AxisOffset(itemSize, gridSize * fraction)
+            val item8Offset = AxisOffset(itemSize, gridSize - gridSize * fraction)
+            val screenSize = itemSize * 3 + spacing * 2
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                if (item1Offset.mainAxis < screenSize) {
+                    add(1 to item1Offset)
+                }
+                add(2 to AxisOffset(0f, itemSizePlusSpacing))
+                add(3 to AxisOffset(itemSize, itemSizePlusSpacing))
+                add(4 to AxisOffset(0f, itemSizePlusSpacing * 2))
+                add(5 to AxisOffset(itemSize, itemSizePlusSpacing * 2))
+                if (item8Offset.mainAxis < screenSize) {
+                    add(8 to item8Offset)
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToTheTopOutsideOfBounds_withSpacing() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11))
+        rule.setContent {
+            LazyStaggeredGrid(
+                2,
+                maxSize = itemSizeDp * 3 + spacingDp * 2,
+                spacing = spacingDp,
+                startIndex = 4
+            ) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            4 to AxisOffset(0f, 0f),
+            5 to AxisOffset(itemSize, 0f),
+            6 to AxisOffset(0f, itemSizePlusSpacing),
+            7 to AxisOffset(itemSize, itemSizePlusSpacing),
+            8 to AxisOffset(0f, itemSizePlusSpacing * 2),
+            9 to AxisOffset(itemSize, itemSizePlusSpacing * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 8, 2, 3, 4, 5, 6, 7, 1, 9, 10, 11)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 8 moves to and item 1 moves from `-itemSize`, right before the start edge
+            val item1Offset = AxisOffset(
+                0f,
+                -itemSize + (itemSize + itemSizePlusSpacing * 2) * fraction
+            )
+            val item8Offset = AxisOffset(
+                0f,
+                itemSizePlusSpacing * 2 -
+                    (itemSize + itemSizePlusSpacing * 2) * fraction
+            )
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                if (item1Offset.mainAxis > -itemSize) {
+                    add(1 to item1Offset)
+                }
+                add(4 to AxisOffset(0f, 0f))
+                add(5 to AxisOffset(itemSize, 0f))
+                add(6 to AxisOffset(0f, itemSizePlusSpacing))
+                add(7 to AxisOffset(itemSize, itemSizePlusSpacing))
+                if (item8Offset.mainAxis > -itemSize) {
+                    add(8 to item8Offset)
+                }
+                add(9 to AxisOffset(itemSize, itemSizePlusSpacing * 2))
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToTheTopOutsideOfBounds_differentSizes() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = itemSize2Dp * 2, startIndex = 6) {
+                items(list, key = { it }) {
+                    val height = when (it) {
+                        2 -> itemSize3Dp
+                        6, 9 -> itemSize2Dp
+                        7 -> itemSize3Dp
+                        8 -> itemSizeDp
+                        else -> itemSizeDp
+                    }
+                    Item(it, size = height)
+                }
+            }
+        }
+
+        val item2Size = itemSize3
+        val item6Size = itemSize2
+        val item7Size = itemSize3
+        val item8Size = itemSize
+        assertPositions(
+            6 to AxisOffset(0f, 0f),
+            7 to AxisOffset(itemSize, 0f),
+            8 to AxisOffset(itemSize, item7Size),
+            9 to AxisOffset(0f, item6Size)
+        )
+
+        rule.runOnUiThread {
+            // swap 8 and 2
+            list = listOf(0, 1, 8, 3, 4, 5, 6, 7, 2, 9, 10, 11)
+        }
+
+        onAnimationFrame { fraction ->
+            rule.onNodeWithTag("3").assertDoesNotExist()
+            rule.onNodeWithTag("4").assertDoesNotExist()
+            rule.onNodeWithTag("5").assertDoesNotExist()
+            // item 2 moves from and item 8 moves to `0 - item size`, right before the start edge
+            val startItem2Offset = -item2Size
+            val item2Offset =
+                startItem2Offset + (item7Size - startItem2Offset) * fraction
+            val endItem8Offset = -item8Size
+            val item8Offset = item7Size - (item7Size - endItem8Offset) * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                if (item8Offset > -item8Size) {
+                    add(8 to AxisOffset(itemSize, item8Offset))
+                } else {
+                    rule.onNodeWithTag("8").assertIsNotDisplayed()
+                }
+                add(6 to AxisOffset(0f, 0f))
+                add(7 to AxisOffset(itemSize, 0f))
+                if (item2Offset > -item2Size) {
+                    add(2 to AxisOffset(itemSize, item2Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                }
+                add(9 to AxisOffset(0f, item6Size))
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToTheBottomOutsideOfBounds_differentSizes() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8))
+        val gridSize = itemSize2 * 2
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    val height = when (it) {
+                        0, 3 -> itemSize2Dp
+                        1 -> itemSize3Dp
+                        2 -> itemSizeDp
+                        8 -> itemSize3Dp
+                        else -> itemSizeDp
+                    }
+                    Item(it, size = height)
+                }
+            }
+        }
+
+        val item0Size = itemSize2
+        val item1Size = itemSize3
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(itemSize, item1Size),
+            3 to AxisOffset(0f, item0Size)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 1, 8, 3, 4, 5, 6, 7, 2, 9, 10, 11)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 8 moves from and item 2 moves to `gridSize`, right after the end edge
+            val startItem8Offset = gridSize
+            val endItem2Offset = gridSize
+            val item2Offset =
+                item1Size + (endItem2Offset - item1Size) * fraction
+            val item8Offset =
+                startItem8Offset - (startItem8Offset - item1Size) * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                add(1 to AxisOffset(itemSize, 0f))
+                if (item8Offset < gridSize) {
+                    add(8 to AxisOffset(itemSize, item8Offset))
+                } else {
+                    rule.onNodeWithTag("8").assertIsNotDisplayed()
+                }
+                add(3 to AxisOffset(0f, item0Size))
+                if (item2Offset < gridSize) {
+                    add(2 to AxisOffset(itemSize, item2Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveItemToEndCausingNextItemsToAnimate_withContentPadding() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        val rawStartPadding = 8f
+        val rawEndPadding = 12f
+        val (startPaddingDp, endPaddingDp) = with(rule.density) {
+            rawStartPadding.toDp() to rawEndPadding.toDp()
+        }
+        rule.setContent {
+            LazyStaggeredGrid(1, startPadding = startPaddingDp, endPadding = endPaddingDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        val startPadding = if (reverseLayout) rawEndPadding else rawStartPadding
+        assertPositions(
+            0 to AxisOffset(0f, startPadding),
+            1 to AxisOffset(0f, startPadding + itemSize),
+            2 to AxisOffset(0f, startPadding + itemSize * 2),
+            3 to AxisOffset(0f, startPadding + itemSize * 3),
+            4 to AxisOffset(0f, startPadding + itemSize * 4),
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 2, 3, 4, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, startPadding),
+                1 to AxisOffset(
+                    0f,
+                    startPadding + itemSize + itemSize * 3 * fraction
+                ),
+                2 to AxisOffset(
+                    0f,
+                    startPadding + itemSize * 2 - itemSize * fraction
+                ),
+                3 to AxisOffset(
+                    0f,
+                    startPadding + itemSize * 3 - itemSize * fraction
+                ),
+                4 to AxisOffset(
+                    0f,
+                    startPadding + itemSize * 4 - itemSize * fraction
+                ),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun reorderFirstAndLastItems_noNewLayoutInfoProduced() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+
+        var measurePasses = 0
+        rule.setContent {
+            LazyStaggeredGrid(1) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+            LaunchedEffect(Unit) {
+                snapshotFlow { state.layoutInfo }
+                    .collect {
+                        measurePasses++
+                    }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(4, 1, 2, 3, 0)
+        }
+
+        var startMeasurePasses = Int.MIN_VALUE
+        onAnimationFrame { fraction ->
+            if (fraction == 0f) {
+                startMeasurePasses = measurePasses
+            }
+        }
+        rule.mainClock.advanceTimeByFrame()
+        // new layoutInfo is produced on every remeasure of Lazy lists.
+        // but we want to avoid remeasuring and only do relayout on each animation frame.
+        // two extra measures are possible as we switch inProgress flag.
+        assertThat(measurePasses).isAtMost(startMeasurePasses + 2)
+    }
+
+    @Test
+    fun noAnimationWhenScrolledToOtherPosition() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollToItem(0, (itemSize / 2).roundToInt())
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, -itemSize / 2),
+                1 to AxisOffset(0f, itemSize / 2),
+                2 to AxisOffset(0f, itemSize * 3 / 2),
+                3 to AxisOffset(0f, itemSize * 5 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollForwardBySmallOffset() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(itemSize / 2f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, -itemSize / 2),
+                1 to AxisOffset(0f, itemSize / 2),
+                2 to AxisOffset(0f, itemSize * 3 / 2),
+                3 to AxisOffset(0f, itemSize * 5 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollBackwardBySmallOffset() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3, startIndex = 2) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(-itemSize / 2f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                1 to AxisOffset(0f, -itemSize / 2),
+                2 to AxisOffset(0f, itemSize / 2),
+                3 to AxisOffset(0f, itemSize * 3 / 2),
+                4 to AxisOffset(0f, itemSize * 5 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollForwardByLargeOffset() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(itemSize * 2.5f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                2 to AxisOffset(0f, -itemSize / 2),
+                3 to AxisOffset(0f, itemSize / 2),
+                4 to AxisOffset(0f, itemSize * 3 / 2),
+                5 to AxisOffset(0f, itemSize * 5 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollBackwardByLargeOffset() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3, startIndex = 3) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(-itemSize * 2.5f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, -itemSize / 2),
+                1 to AxisOffset(0f, itemSize / 2),
+                2 to AxisOffset(0f, itemSize * 3 / 2),
+                3 to AxisOffset(0f, itemSize * 5 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollForwardByLargeOffset_differentSizes() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it, size = if (it % 2 == 0) itemSizeDp else itemSize2Dp)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(itemSize + itemSize2 + itemSize / 2f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                2 to AxisOffset(0f, -itemSize / 2),
+                3 to AxisOffset(0f, itemSize / 2),
+                4 to AxisOffset(0f, itemSize2 + itemSize / 2),
+                5 to AxisOffset(0f, itemSize2 + itemSize * 3 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollBackwardByLargeOffset_differentSizes() {
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3, startIndex = 3) {
+                items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
+                    Item(it, size = if (it % 2 == 0) itemSizeDp else itemSize2Dp)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(-(itemSize + itemSize2 + itemSize / 2f))
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, -itemSize / 2),
+                1 to AxisOffset(0f, itemSize / 2),
+                2 to AxisOffset(0f, itemSize2 + itemSize / 2),
+                3 to AxisOffset(0f, itemSize2 + itemSize * 3 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollForwardByLargeOffset_multipleCells() {
+        rule.setContent {
+            LazyStaggeredGrid(3, maxSize = itemSizeDp * 2) {
+                items(List(20) { it }, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(itemSize * 2, 0f),
+            3 to AxisOffset(0f, itemSize),
+            4 to AxisOffset(itemSize, itemSize),
+            5 to AxisOffset(itemSize * 2, itemSize)
+        )
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(itemSize * 2.5f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                6 to AxisOffset(0f, -itemSize / 2),
+                7 to AxisOffset(itemSize, -itemSize / 2),
+                8 to AxisOffset(itemSize * 2, -itemSize / 2),
+                9 to AxisOffset(0f, itemSize / 2),
+                10 to AxisOffset(itemSize, itemSize / 2),
+                11 to AxisOffset(itemSize * 2, itemSize / 2),
+                12 to AxisOffset(0f, itemSize * 3 / 2),
+                13 to AxisOffset(itemSize, itemSize * 3 / 2),
+                14 to AxisOffset(itemSize * 2, itemSize * 3 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollBackwardByLargeOffset_multipleCells() {
+        rule.setContent {
+            LazyStaggeredGrid(3, maxSize = itemSizeDp * 2, startIndex = 9) {
+                items(List(20) { it }, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            9 to AxisOffset(0f, 0f),
+            10 to AxisOffset(itemSize, 0f),
+            11 to AxisOffset(itemSize * 2, 0f),
+            12 to AxisOffset(0f, itemSize),
+            13 to AxisOffset(itemSize, itemSize),
+            14 to AxisOffset(itemSize * 2, itemSize)
+        )
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(-itemSize * 2.5f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, -itemSize / 2),
+                1 to AxisOffset(itemSize, -itemSize / 2),
+                2 to AxisOffset(itemSize * 2, -itemSize / 2),
+                3 to AxisOffset(0f, itemSize / 2),
+                4 to AxisOffset(itemSize, itemSize / 2),
+                5 to AxisOffset(itemSize * 2, itemSize / 2),
+                6 to AxisOffset(0f, itemSize * 3 / 2),
+                7 to AxisOffset(itemSize, itemSize * 3 / 2),
+                8 to AxisOffset(itemSize * 2, itemSize * 3 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollForwardByLargeOffset_differentSpans() {
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = itemSizeDp * 2) {
+                items(
+                    List(10) { it },
+                    key = { it },
+                    span = {
+                        if (it == 6) {
+                            StaggeredGridItemSpan.FullLine
+                        } else {
+                            StaggeredGridItemSpan.SingleLane
+                        }
+                    }
+                ) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize),
+        )
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(itemSize * 2.5f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                4 to AxisOffset(0f, -itemSize / 2),
+                5 to AxisOffset(itemSize, -itemSize / 2),
+                6 to AxisOffset(0f, itemSize / 2), // 3 spans
+                7 to AxisOffset(0f, itemSize * 3 / 2),
+                8 to AxisOffset(itemSize, itemSize * 3 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenScrollBackwardByLargeOffset_differentSpans() {
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = itemSizeDp * 2) {
+                items(
+                    List(10) { it },
+                    key = { it },
+                    span = {
+                        if (it == 2) {
+                            StaggeredGridItemSpan.FullLine
+                        } else {
+                            StaggeredGridItemSpan.SingleLane
+                        }
+                    }
+                ) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(itemSize * 3f)
+            }
+        }
+
+        assertPositions(
+            5 to AxisOffset(0f, 0f),
+            6 to AxisOffset(itemSize, 0f),
+            7 to AxisOffset(0f, itemSize),
+            8 to AxisOffset(itemSize, itemSize),
+        )
+
+        rule.runOnUiThread {
+            runBlocking {
+                state.scrollBy(-itemSize * 2.5f)
+            }
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, -itemSize / 2),
+                1 to AxisOffset(itemSize, -itemSize / 2),
+                2 to AxisOffset(0f, itemSize / 2), // 3 spans
+                3 to AxisOffset(0f, itemSize * 3 / 2),
+                4 to AxisOffset(itemSize, itemSize * 3 / 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun animatingItemWithPreviousIndexLargerThanTheNewItemCount() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7))
+        val gridSize = itemSize * 2
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertLayoutInfoPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, itemSize),
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 6)
+        }
+
+        onAnimationFrame { fraction ->
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                val item6MainAxis = gridSize - (gridSize - itemSize) * fraction
+                if (item6MainAxis < gridSize) {
+                    add(6 to AxisOffset(0f, item6MainAxis))
+                } else {
+                    rule.onNodeWithTag("6").assertIsNotDisplayed()
+                }
+            }
+
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun animatingItemsWithPreviousIndexLargerThanTheNewItemCount_differentSpans() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6))
+        val gridSize = itemSize * 2
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = gridSizeDp) {
+                items(list, key = { it }, span = {
+                    if (it == 6) {
+                        StaggeredGridItemSpan.FullLine
+                    } else {
+                        StaggeredGridItemSpan.SingleLane
+                    }
+                }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertLayoutInfoPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 4, 6)
+        }
+
+        onAnimationFrame { fraction ->
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                val item4MainAxis = gridSize - gridSize * fraction
+                if (item4MainAxis < gridSize) {
+                    add(
+                        4 to AxisOffset(itemSize, item4MainAxis)
+                    )
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                }
+                val item6MainAxis = gridSize - (gridSize - itemSize) * fraction
+                if (item6MainAxis < gridSize) {
+                    add(
+                        6 to AxisOffset(0f, item6MainAxis)
+                    )
+                } else {
+                    rule.onNodeWithTag("6").assertIsNotDisplayed()
+                }
+            }
+
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun itemWithSpecsIsMovingOut() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3))
+        val gridSize = itemSize * 2
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    Item(it, animSpec = if (it == 1) AnimSpec else null)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(0, 2, 3, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 1 moves to `gridSize`
+            val item1Offset = itemSize + (gridSize - itemSize) * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                if (item1Offset < gridSize) {
+                    add(1 to AxisOffset(0f, item1Offset))
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveTwoItemsToTheTopOutsideOfBounds() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5))
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3f, startIndex = 3) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            3 to AxisOffset(0f, 0f),
+            4 to AxisOffset(0f, itemSize),
+            5 to AxisOffset(0f, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 4, 5, 3, 1, 2)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 2 moves from and item 5 moves to `-itemSize`, right before the start edge
+            val item2Offset = -itemSize + itemSize * 3 * fraction
+            val item5Offset = itemSize * 2 - itemSize * 3 * fraction
+            // item 1 moves from and item 4 moves to `-itemSize * 2`, right before item 2
+            val item1Offset = -itemSize * 2 + itemSize * 3 * fraction
+            val item4Offset = itemSize - itemSize * 3 * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                if (item1Offset > -itemSize) {
+                    add(1 to AxisOffset(0f, item1Offset))
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                if (item2Offset > -itemSize) {
+                    add(2 to AxisOffset(0f, item2Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                }
+                add(3 to AxisOffset(0f, 0f))
+                if (item4Offset > -itemSize) {
+                    add(4 to AxisOffset(0f, item4Offset))
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                }
+                if (item5Offset > -itemSize) {
+                    add(5 to AxisOffset(0f, item5Offset))
+                } else {
+                    rule.onNodeWithTag("5").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveTwoItemsToTheTopOutsideOfBounds_withReordering() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5))
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 3f, startIndex = 3) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            3 to AxisOffset(0f, 0f),
+            4 to AxisOffset(0f, itemSize),
+            5 to AxisOffset(0f, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 5, 4, 3, 2, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 2 moves from and item 4 moves to `-itemSize`, right before the start edge
+            val item2Offset = -itemSize + itemSize * 2 * fraction
+            val item4Offset = itemSize - itemSize * 2 * fraction
+            // item 1 moves from and item 5 moves to `-itemSize * 2`, right before item 2
+            val item1Offset = -itemSize * 2 + itemSize * 4 * fraction
+            val item5Offset = itemSize * 2 - itemSize * 4 * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                if (item1Offset > -itemSize) {
+                    add(1 to AxisOffset(0f, item1Offset))
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                if (item2Offset > -itemSize) {
+                    add(2 to AxisOffset(0f, item2Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                }
+                add(3 to AxisOffset(0f, 0f))
+                if (item4Offset > -itemSize) {
+                    add(4 to AxisOffset(0f, item4Offset))
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                }
+                if (item5Offset > -itemSize) {
+                    add(5 to AxisOffset(0f, item5Offset))
+                } else {
+                    rule.onNodeWithTag("5").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveTwoItemsToTheTopOutsideOfBounds_itemsOfDifferentLanes() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5))
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = itemSizeDp * 2f, startIndex = 2) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            2 to AxisOffset(0f, 0f),
+            3 to AxisOffset(itemSize, 0f),
+            4 to AxisOffset(0f, itemSize),
+            5 to AxisOffset(itemSize, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(4, 5, 2, 3, 0, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            // items 0 and 2 moves from and items 4 and 5 moves to `-itemSize`,
+            // right before the start edge
+            val items0and1Offset = -itemSize + itemSize * 2 * fraction
+            val items4and5Offset = itemSize - itemSize * 2 * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                if (items0and1Offset > -itemSize) {
+                    add(0 to AxisOffset(0f, items0and1Offset))
+                    add(1 to AxisOffset(itemSize, items0and1Offset))
+                } else {
+                    rule.onNodeWithTag("0").assertIsNotDisplayed()
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                add(2 to AxisOffset(0f, 0f))
+                add(3 to AxisOffset(itemSize, 0f))
+                if (items4and5Offset > -itemSize) {
+                    add(4 to AxisOffset(0f, items4and5Offset))
+                    add(5 to AxisOffset(itemSize, items4and5Offset))
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                    rule.onNodeWithTag("5").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveTwoItemsToTheBottomOutsideOfBounds() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        val gridSize = itemSize * 3
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, itemSize),
+            2 to AxisOffset(0f, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 3, 4, 1, 2)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 1 moves to and item 3 moves from `gridSize`, right after the end edge
+            val item1Offset = itemSize + (gridSize - itemSize) * fraction
+            val item3Offset = gridSize - (gridSize - itemSize) * fraction
+            // item 2 moves to and item 4 moves from `gridSize + itemSize`, right after item 4
+            val item2Offset = itemSize * 2 + (gridSize - itemSize) * fraction
+            val item4Offset = gridSize + itemSize - (gridSize - itemSize) * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                if (item1Offset < gridSize) {
+                    add(1 to AxisOffset(0f, item1Offset))
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                if (item2Offset < gridSize) {
+                    add(2 to AxisOffset(0f, item2Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                }
+                if (item3Offset < gridSize) {
+                    add(3 to AxisOffset(0f, item3Offset))
+                } else {
+                    rule.onNodeWithTag("3").assertIsNotDisplayed()
+                }
+                if (item4Offset < gridSize) {
+                    add(4 to AxisOffset(0f, item4Offset))
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveTwoItemsToTheBottomOutsideOfBounds_withReordering() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        val gridSize = itemSize * 3
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(0f, itemSize),
+            2 to AxisOffset(0f, itemSize * 2)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 4, 3, 2, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            // item 2 moves to and item 3 moves from `gridSize`, right after the end edge
+            val item2Offset = itemSize * 2 + (gridSize - itemSize * 2) * fraction
+            val item3Offset = gridSize - (gridSize - itemSize * 2) * fraction
+            // item 1 moves to and item 4 moves from `gridSize + itemSize`, right after item 4
+            val item1Offset = itemSize + (gridSize + itemSize - itemSize) * fraction
+            val item4Offset =
+                gridSize + itemSize - (gridSize + itemSize - itemSize) * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                if (item1Offset < gridSize) {
+                    add(1 to AxisOffset(0f, item1Offset))
+                } else {
+                    rule.onNodeWithTag("1").assertIsNotDisplayed()
+                }
+                if (item2Offset < gridSize) {
+                    add(2 to AxisOffset(0f, item2Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                }
+                if (item3Offset < gridSize) {
+                    add(3 to AxisOffset(0f, item3Offset))
+                } else {
+                    rule.onNodeWithTag("3").assertIsNotDisplayed()
+                }
+                if (item4Offset < gridSize) {
+                    add(4 to AxisOffset(0f, item4Offset))
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun moveTwoItemsToTheBottomOutsideOfBounds_itemsOfDifferentLanes() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4, 5))
+        val gridSize = itemSize * 2
+        val gridSizeDp = with(rule.density) { gridSize.toDp() }
+        rule.setContent {
+            LazyStaggeredGrid(2, maxSize = gridSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        assertPositions(
+            0 to AxisOffset(0f, 0f),
+            1 to AxisOffset(itemSize, 0f),
+            2 to AxisOffset(0f, itemSize),
+            3 to AxisOffset(itemSize, itemSize)
+        )
+
+        rule.runOnUiThread {
+            list = listOf(0, 1, 4, 5, 2, 3)
+        }
+
+        onAnimationFrame { fraction ->
+            // items 4 and 5 moves from and items 2 and 3 moves to `gridSize`,
+            // right before the start edge
+            val items4and5Offset = gridSize - (gridSize - itemSize) * fraction
+            val items2and3Offset = itemSize + (gridSize - itemSize) * fraction
+            val expected = mutableListOf<Pair<Any, Offset>>().apply {
+                add(0 to AxisOffset(0f, 0f))
+                add(1 to AxisOffset(itemSize, 0f))
+                if (items2and3Offset < gridSize) {
+                    add(2 to AxisOffset(0f, items2and3Offset))
+                    add(3 to AxisOffset(itemSize, items2and3Offset))
+                } else {
+                    rule.onNodeWithTag("2").assertIsNotDisplayed()
+                    rule.onNodeWithTag("3").assertIsNotDisplayed()
+                }
+                if (items4and5Offset < gridSize) {
+                    add(4 to AxisOffset(0f, items4and5Offset))
+                    add(5 to AxisOffset(itemSize, items4and5Offset))
+                } else {
+                    rule.onNodeWithTag("4").assertIsNotDisplayed()
+                    rule.onNodeWithTag("5").assertIsNotDisplayed()
+                }
+            }
+            assertPositions(
+                expected = expected.toTypedArray(),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun noAnimationWhenParentSizeShrinks() {
+        var size by mutableStateOf(itemSizeDp * 3)
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = size) {
+                items(listOf(0, 1, 2), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            size = itemSizeDp * 2
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0f),
+                1 to AxisOffset(0f, itemSize),
+                fraction = fraction
+            )
+            rule.onNodeWithTag("2").assertIsNotDisplayed()
+        }
+    }
+
+    @Test
+    fun noAnimationWhenParentSizeExpands() {
+        var size by mutableStateOf(itemSizeDp * 2)
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = size) {
+                items(listOf(0, 1, 2), key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            size = itemSizeDp * 3
+        }
+
+        onAnimationFrame { fraction ->
+            assertPositions(
+                0 to AxisOffset(0f, 0f),
+                1 to AxisOffset(0f, itemSize),
+                2 to AxisOffset(0f, itemSize * 2),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun scrollIsAffectingItemsMovingWithinViewport() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3))
+        val scrollDelta = spacing
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = itemSizeDp * 2) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(0, 2, 1, 3)
+        }
+
+        onAnimationFrame { fraction ->
+            if (fraction == 0f) {
+                assertPositions(
+                    0 to AxisOffset(0f, 0f),
+                    1 to AxisOffset(0f, itemSize),
+                    2 to AxisOffset(0f, itemSize * 2),
+                    fraction = fraction
+                )
+                rule.runOnUiThread {
+                    runBlocking { state.scrollBy(scrollDelta) }
+                }
+            }
+            assertPositions(
+                0 to AxisOffset(0f, -scrollDelta),
+                1 to AxisOffset(0f, itemSize - scrollDelta + itemSize * fraction),
+                2 to AxisOffset(0f, itemSize * 2 - scrollDelta - itemSize * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun scrollIsNotAffectingItemMovingToTheBottomOutsideOfBounds() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        val scrollDelta = spacing
+        val containerSizeDp = itemSizeDp * 2
+        val containerSize = itemSize * 2
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = containerSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(0, 4, 2, 3, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            if (fraction == 0f) {
+                assertPositions(
+                    0 to AxisOffset(0f, 0f),
+                    1 to AxisOffset(0f, itemSize),
+                    fraction = fraction
+                )
+                rule.runOnUiThread {
+                    runBlocking { state.scrollBy(scrollDelta) }
+                }
+            }
+            assertPositions(
+                0 to AxisOffset(0f, -scrollDelta),
+                1 to AxisOffset(0f, itemSize + (containerSize - itemSize) * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun scrollIsNotAffectingItemMovingToTheTopOutsideOfBounds() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        val scrollDelta = -spacing
+        val containerSizeDp = itemSizeDp * 2
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = containerSizeDp, startIndex = 2) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(3, 0, 1, 2, 4)
+        }
+
+        onAnimationFrame { fraction ->
+            if (fraction == 0f) {
+                assertPositions(
+                    2 to AxisOffset(0f, 0f),
+                    3 to AxisOffset(0f, itemSize),
+                    fraction = fraction
+                )
+                rule.runOnUiThread {
+                    runBlocking { state.scrollBy(scrollDelta) }
+                }
+            }
+            assertPositions(
+                2 to AxisOffset(0f, -scrollDelta),
+                3 to AxisOffset(0f, itemSize - (itemSize * 2 * fraction)),
+                fraction = fraction
+            )
+        }
+    }
+
+    @Test
+    fun afterScrollingEnoughToReachNewPositionScrollDeltasStartAffectingPosition() {
+        var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
+        val containerSizeDp = itemSizeDp * 2
+        val scrollDelta = spacing
+        rule.setContent {
+            LazyStaggeredGrid(1, maxSize = containerSizeDp) {
+                items(list, key = { it }) {
+                    Item(it)
+                }
+            }
+        }
+
+        rule.runOnUiThread {
+            list = listOf(0, 4, 2, 3, 1)
+        }
+
+        onAnimationFrame { fraction ->
+            if (fraction == 0f) {
+                assertPositions(
+                    0 to AxisOffset(0f, 0f),
+                    1 to AxisOffset(0f, itemSize),
+                    fraction = fraction
+                )
+                rule.runOnUiThread {
+                    runBlocking { state.scrollBy(itemSize * 2) }
+                }
+                assertPositions(
+                    2 to AxisOffset(0f, 0f),
+                    3 to AxisOffset(0f, itemSize),
+                    // after the first scroll the new position of item 1 is still not reached
+                    // so the target didn't change, we still aim to end right after the bounds
+                    1 to AxisOffset(0f, itemSize),
+                    fraction = fraction
+                )
+                rule.runOnUiThread {
+                    runBlocking { state.scrollBy(scrollDelta) }
+                }
+                assertPositions(
+                    2 to AxisOffset(0f, 0f - scrollDelta),
+                    3 to AxisOffset(0f, itemSize - scrollDelta),
+                    // after the second scroll the item 1 is visible, so we know its new target
+                    // position. the animation is now targeting the real end position and now
+                    // we are reacting on the scroll deltas
+                    1 to AxisOffset(0f, itemSize - scrollDelta),
+                    fraction = fraction
+                )
+            }
+            assertPositions(
+                2 to AxisOffset(0f, -scrollDelta),
+                3 to AxisOffset(0f, itemSize - scrollDelta),
+                1 to AxisOffset(0f, itemSize - scrollDelta + itemSize * fraction),
+                fraction = fraction
+            )
+        }
+    }
+
+    private fun AxisOffset(crossAxis: Float, mainAxis: Float) =
+        if (isVertical) Offset(crossAxis, mainAxis) else Offset(mainAxis, crossAxis)
+
+    private val Offset.mainAxis: Float get() = if (isVertical) y else x
+
+    private fun assertPositions(
+        vararg expected: Pair<Any, Offset>,
+        crossAxis: List<Pair<Any, Float>>? = null,
+        fraction: Float? = null,
+        autoReverse: Boolean = reverseLayout
+    ) {
+        val roundedExpected = expected.map { it.first to it.second.round() }
+        val actualBounds = rule.onAllNodes(NodesWithTagMatcher)
+            .fetchSemanticsNodes()
+            .associateBy(
+                keySelector = { it.config[SemanticsProperties.TestTag] },
+                valueTransform = { IntRect(it.positionInRoot.round(), it.size) }
+            )
+        val actualPositions = expected.map {
+            it.first to actualBounds.getValue(it.first.toString()).topLeft
+        }
+        val subject = if (fraction == null) {
+            assertThat(actualPositions)
+        } else {
+            Truth.assertWithMessage("Fraction=$fraction").that(actualPositions)
+        }
+        subject.isEqualTo(
+            roundedExpected.let { list ->
+                if (!autoReverse) {
+                    list
+                } else {
+                    val containerSize = actualBounds.getValue(ContainerTag).size
+                    list.map {
+                        val itemSize = actualBounds.getValue(it.first.toString()).size
+                        it.first to
+                            IntOffset(
+                                if (isVertical) {
+                                    it.second.x
+                                } else {
+                                    containerSize.width - itemSize.width - it.second.x
+                                },
+                                if (!isVertical) {
+                                    it.second.y
+                                } else {
+                                    containerSize.height - itemSize.height - it.second.y
+                                }
+                            )
+                    }
+                }
+            }
+        )
+        if (crossAxis != null) {
+            val actualCross = expected.map {
+                it.first to actualBounds.getValue(it.first.toString()).topLeft
+                    .let { offset -> if (isVertical) offset.x else offset.y }
+            }
+            Truth.assertWithMessage(
+                "CrossAxis" + if (fraction != null) "for fraction=$fraction" else ""
+            )
+                .that(actualCross)
+                .isEqualTo(crossAxis.map { it.first to it.second.roundToInt() })
+        }
+    }
+
+    private fun assertLayoutInfoPositions(vararg offsets: Pair<Any, Offset>) {
+        rule.runOnIdle {
+            assertThat(visibleItemsOffsets).isEqualTo(offsets.map { it.first to it.second.round() })
+        }
+    }
+
+    private val visibleItemsOffsets: List<Pair<Any, IntOffset>>
+        get() = state.layoutInfo.visibleItemsInfo.map {
+            it.key to it.offset
+        }
+
+    private fun onAnimationFrame(duration: Long = Duration, onFrame: (fraction: Float) -> Unit) {
+        require(duration.mod(FrameDuration) == 0L)
+        rule.waitForIdle()
+        rule.mainClock.advanceTimeByFrame()
+        var expectedTime = rule.mainClock.currentTime
+        for (i in 0..duration step FrameDuration) {
+            val fraction = i / duration.toFloat()
+            onFrame(fraction)
+            rule.mainClock.advanceTimeBy(FrameDuration)
+            expectedTime += FrameDuration
+            assertThat(expectedTime).isEqualTo(rule.mainClock.currentTime)
+        }
+    }
+
+    @Composable
+    private fun LazyStaggeredGrid(
+        cells: Int,
+        minSize: Dp = 0.dp,
+        maxSize: Dp = containerSizeDp,
+        startIndex: Int = 0,
+        startPadding: Dp = 0.dp,
+        endPadding: Dp = 0.dp,
+        spacing: Dp = 0.dp,
+        content: LazyStaggeredGridScope.() -> Unit
+    ) {
+        state = rememberLazyStaggeredGridState(startIndex)
+        if (isVertical) {
+            LazyVerticalStaggeredGrid(
+                StaggeredGridCells.Fixed(cells),
+                Modifier
+                    .requiredHeightIn(minSize, maxSize)
+                    .requiredWidth(itemSizeDp * cells)
+                    .testTag(ContainerTag),
+                state = state,
+                verticalItemSpacing = spacing,
+                reverseLayout = reverseLayout,
+                contentPadding = PaddingValues(top = startPadding, bottom = endPadding),
+                content = content
+            )
+        } else {
+            LazyHorizontalStaggeredGrid(
+                StaggeredGridCells.Fixed(cells),
+                Modifier
+                    .requiredWidthIn(minSize, maxSize)
+                    .requiredHeight(itemSizeDp * cells)
+                    .testTag(ContainerTag),
+                state = state,
+                reverseLayout = reverseLayout,
+                horizontalItemSpacing = spacing,
+                contentPadding = PaddingValues(start = startPadding, end = endPadding),
+                content = content
+            )
+        }
+    }
+
+    @Composable
+    private fun LazyStaggeredGridItemScope.Item(
+        tag: Int,
+        size: Dp = itemSizeDp,
+        animSpec: FiniteAnimationSpec<IntOffset>? = AnimSpec
+    ) {
+        Box(
+            if (animSpec != null) {
+                Modifier.animateItemPlacement(animSpec)
+            } else {
+                Modifier
+            }
+                .then(
+                    if (isVertical) {
+                        Modifier.requiredHeight(size)
+                    } else {
+                        Modifier.requiredWidth(size)
+                    }
+                )
+                .testTag(tag.toString())
+        )
+    }
+
+    private fun SemanticsNodeInteraction.assertMainAxisSizeIsEqualTo(
+        expected: Dp
+    ): SemanticsNodeInteraction {
+        return if (isVertical) assertHeightIsEqualTo(expected) else assertWidthIsEqualTo(expected)
+    }
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun params() = arrayOf(
+            Config(isVertical = true, reverseLayout = false),
+            Config(isVertical = false, reverseLayout = false),
+            Config(isVertical = true, reverseLayout = true),
+            Config(isVertical = false, reverseLayout = true),
+        )
+
+        class Config(
+            val isVertical: Boolean,
+            val reverseLayout: Boolean
+        ) {
+            override fun toString() =
+                (if (isVertical) "LazyVerticalGrid" else "LazyHorizontalGrid") +
+                    (if (reverseLayout) "(reverse)" else "")
+        }
+    }
+}
+
+private val FrameDuration = 16L
+private val Duration = 64L // 4 frames, so we get 0f, 0.25f, 0.5f, 0.75f and 1f fractions
+private val AnimSpec = tween<IntOffset>(Duration.toInt(), easing = LinearEasing)
+private val ContainerTag = "container"
+private val NodesWithTagMatcher = SemanticsMatcher("NodesWithTag") {
+    it.config.contains(SemanticsProperties.TestTag)
+}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimatedScrollTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimatedScrollTest.kt
index 627f6fb..d68ad55 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimatedScrollTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimatedScrollTest.kt
@@ -69,16 +69,22 @@
         itemSizeDp = with(rule.density) {
             itemSizePx.toDp()
         }
+    }
+
+    private fun testScroll(spacingPx: Int = 0, assertBlock: suspend () -> Unit) {
         rule.setContent {
-            scope = rememberCoroutineScope()
             state = rememberLazyStaggeredGridState()
-            TestContent()
+            scope = rememberCoroutineScope()
+            TestContent(with(rule.density) { spacingPx.toDp() })
         }
         rule.waitForIdle()
+        runBlocking {
+            assertBlock()
+        }
     }
 
     @Test
-    fun animateScrollBy() = runBlocking {
+    fun animateScrollBy() = testScroll {
         val scrollDistance = 320
 
         val expectedIndex = scrollDistance * 2 / itemSizePx // resolves to 6
@@ -92,7 +98,7 @@
     }
 
     @Test
-    fun animateScrollToItem_positiveOffset() = runBlocking {
+    fun animateScrollToItem_positiveOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(10, 10)
         }
@@ -101,7 +107,7 @@
     }
 
     @Test
-    fun animateScrollToItem_positiveOffset_largerThanItem() = runBlocking {
+    fun animateScrollToItem_positiveOffset_largerThanItem() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(10, 150)
         }
@@ -110,7 +116,7 @@
     }
 
     @Test
-    fun animateScrollToItem_negativeOffset() = runBlocking {
+    fun animateScrollToItem_negativeOffset() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(10, -10)
         }
@@ -119,7 +125,7 @@
     }
 
     @Test
-    fun animateScrollToItem_beforeFirstItem() = runBlocking {
+    fun animateScrollToItem_beforeFirstItem() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(10)
             state.animateScrollToItem(0, -10)
@@ -129,7 +135,7 @@
     }
 
     @Test
-    fun animateScrollToItem_afterLastItem() {
+    fun animateScrollToItem_afterLastItem() = testScroll {
         runBlocking(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(100)
         }
@@ -139,7 +145,7 @@
     }
 
     @Test
-    fun animateScrollToItem_toFullSpan() {
+    fun animateScrollToItem_toFullSpan() = testScroll {
         runBlocking(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(50, 10)
         }
@@ -149,7 +155,7 @@
     }
 
     @Test
-    fun animateScrollToItem_toFullSpan_andBack() {
+    fun animateScrollToItem_toFullSpan_andBack() = testScroll {
         runBlocking(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(50, 10)
         }
@@ -164,32 +170,32 @@
     }
 
     @Test
-    fun animateScrollToItem_inBounds() {
+    fun animateScrollToItem_inBounds() = testScroll {
         assertSpringAnimation(2)
     }
 
     @Test
-    fun animateScrollToItem_inBounds_withOffset() {
+    fun animateScrollToItem_inBounds_withOffset() = testScroll {
         assertSpringAnimation(2, itemSizePx / 2)
     }
 
     @Test
-    fun animateScrollToItem_outOfBounds() {
+    fun animateScrollToItem_outOfBounds() = testScroll {
         assertSpringAnimation(10)
     }
 
     @Test
-    fun animateScrollToItem_firstItem() {
+    fun animateScrollToItem_firstItem() = testScroll {
         assertSpringAnimation(fromIndex = 10, fromOffset = 10, toIndex = 0)
     }
 
     @Test
-    fun animateScrollToItem_firstItem_toOffset() {
+    fun animateScrollToItem_firstItem_toOffset() = testScroll {
         assertSpringAnimation(fromIndex = 10, fromOffset = 10, toIndex = 0, toOffset = 10)
     }
 
     @Test
-    fun animateScrollToItemWithOffsetLargerThanItemSize_forward() {
+    fun animateScrollToItemWithOffsetLargerThanItemSize_forward() = testScroll {
         runBlocking(Dispatchers.Main + AutoTestFrameClock()) {
             state.animateScrollToItem(20, -itemSizePx * 3)
         }
@@ -199,7 +205,7 @@
     }
 
     @Test
-    fun animateScrollToItemWithOffsetLargerThanItemSize_backward() = runBlocking {
+    fun animateScrollToItemWithOffsetLargerThanItemSize_backward() = testScroll {
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToItem(20)
             state.animateScrollToItem(0, itemSizePx * 3)
@@ -208,11 +214,32 @@
         assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
     }
 
+    @Test
+    fun animateScrollToItem_outOfBounds_withSpacing() = testScroll(spacingPx = 10) {
+        assertSpringAnimation(20, spacingPx = 10)
+    }
+
+    @Test
+    fun animateScrollToItem_outOfBounds_withNegativeSpacing() = testScroll(spacingPx = -10) {
+        assertSpringAnimation(20, spacingPx = -10)
+    }
+
+    @Test
+    fun animateScrollToItem_backwards_withSpacing() = testScroll(spacingPx = 10) {
+        assertSpringAnimation(toIndex = 0, fromIndex = 20, spacingPx = 10)
+    }
+
+    @Test
+    fun animateScrollToItem_backwards_withNegativeSpacing() = testScroll(spacingPx = -10) {
+        assertSpringAnimation(toIndex = 0, fromIndex = 20, spacingPx = -10)
+    }
+
     private fun assertSpringAnimation(
         toIndex: Int,
         toOffset: Int = 0,
         fromIndex: Int = 0,
-        fromOffset: Int = 0
+        fromOffset: Int = 0,
+        spacingPx: Int = 0
     ) {
         if (fromIndex != 0 || fromOffset != 0) {
             rule.runOnIdle {
@@ -236,8 +263,10 @@
             Thread.sleep(5)
         }
 
-        val startOffset = (fromIndex / 2 * itemSizePx + fromOffset).toFloat()
-        val endOffset = (toIndex / 2 * itemSizePx + toOffset).toFloat()
+        val itemSizeWSpacing = spacingPx + itemSizePx
+        val startOffset = (fromIndex / 2 * itemSizeWSpacing + fromOffset).toFloat()
+        val endOffset = (toIndex / 2 * itemSizeWSpacing + toOffset).toFloat()
+
         val spec = FloatSpringSpec()
 
         val duration =
@@ -250,9 +279,10 @@
             val expectedValue =
                 spec.getValueFromNanos(nanosTime, startOffset, endOffset, 0f)
             val actualValue =
-                (state.firstVisibleItemIndex / 2 * itemSizePx + state.firstVisibleItemScrollOffset)
+                (state.firstVisibleItemIndex / 2 * itemSizeWSpacing +
+                    state.firstVisibleItemScrollOffset)
             assertWithMessage(
-                "On animation frame at $i index=${state.firstVisibleItemIndex} " +
+                "On animation frame at ${i}ms index=${state.firstVisibleItemIndex} " +
                     "offset=${state.firstVisibleItemScrollOffset} expectedValue=$expectedValue"
             ).that(actualValue).isEqualTo(expectedValue.roundToInt(), tolerance = 1)
 
@@ -266,11 +296,12 @@
     }
 
     @Composable
-    private fun TestContent() {
+    private fun TestContent(spacingDp: Dp) {
         LazyStaggeredGrid(
             lanes = 2,
             state = state,
-            modifier = Modifier.axisSize(itemSizeDp * 2, itemSizeDp * 5)
+            modifier = Modifier.axisSize(itemSizeDp * 2, itemSizeDp * 5),
+            mainAxisSpacing = spacingDp
         ) {
             items(
                 count = 100,
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt
index 74e519c..01f2c1c 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt
@@ -48,7 +48,6 @@
 
 package androidx.compose.foundation.lazy.staggeredgrid
 
-import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -62,13 +61,12 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.test.filters.MediumTest
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-@OptIn(ExperimentalFoundationApi::class)
 @MediumTest
 @RunWith(Parameterized::class)
 class LazyStaggeredGridArrangementsTest(
@@ -220,6 +218,55 @@
         rule.onNodeWithTag("2")
             .assertMainAxisStartPositionInRootIsEqualTo(0.dp)
             .assertMainAxisSizeIsEqualTo(itemSizeDp * 2)
+
+        assertThat(state.firstVisibleItemIndex).isEqualTo(2)
+        assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+    }
+
+    @Test
+    fun negativeSpacing_withContentPadding_itemsVisible() {
+        state = LazyStaggeredGridState()
+        rule.setContent {
+            LazyStaggeredGrid(
+                lanes = 2,
+                modifier = Modifier
+                    .testTag(LazyStaggeredGrid)
+                    .axisSize(itemSizeDp * 2, itemSizeDp * 5),
+                state = state,
+                mainAxisSpacing = -itemSizeDp,
+                contentPadding = PaddingValues(beforeContent = itemSizeDp)
+            ) {
+                items(100) {
+                    BasicText(
+                        text = "$it",
+                        modifier = Modifier
+                            .testTag("$it")
+                            .mainAxisSize(itemSizeDp * 2)
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag("0")
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSizeDp)
+            .assertMainAxisSizeIsEqualTo(itemSizeDp * 2)
+
+        rule.onNodeWithTag("2")
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSizeDp * 2)
+            .assertMainAxisSizeIsEqualTo(itemSizeDp * 2)
+
+        state.scrollBy(itemSizeDp)
+
+        rule.onNodeWithTag("0")
+            .assertMainAxisStartPositionInRootIsEqualTo(0.dp)
+            .assertMainAxisSizeIsEqualTo(itemSizeDp * 2)
+
+        rule.onNodeWithTag("2")
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSizeDp)
+            .assertMainAxisSizeIsEqualTo(itemSizeDp * 2)
+
+        assertThat(state.firstVisibleItemIndex).isEqualTo(2)
+        assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
     }
 
     @Test
@@ -245,8 +292,8 @@
         }
 
         rule.runOnIdle {
-            Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(0)
-            Truth.assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
         }
     }
 
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridReverseLayoutTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridReverseLayoutTest.kt
index 54057c2..6af08de 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridReverseLayoutTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridReverseLayoutTest.kt
@@ -397,9 +397,40 @@
 
         // bottom padding applies instead of the top
         rule.onNodeWithTag("0")
-            .assertMainAxisStartPositionInRootIsEqualTo(itemSize * 3)
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSize * 2)
         rule.onNodeWithTag("1")
-            .assertMainAxisStartPositionInRootIsEqualTo(itemSize * 3)
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSize * 2)
+    }
+
+    @Test
+    fun contentPadding_isPreserved() {
+        val state = LazyStaggeredGridState()
+        rule.setContent {
+            LazyStaggeredGrid(
+                lanes = 2,
+                modifier = Modifier
+                    .axisSize(itemSize * 2, itemSize * 5)
+                    .testTag(StaggeredGridTag),
+                contentPadding = PaddingValues(afterContent = itemSize * 2),
+                reverseLayout = true,
+                state = state
+            ) {
+                items(6) {
+                    Box(Modifier.size(itemSize).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+        }
+
+        // bottom padding applies instead of the top
+        rule.onNodeWithTag("0")
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSize * 2)
+        rule.onNodeWithTag("1")
+            .assertMainAxisStartPositionInRootIsEqualTo(itemSize * 2)
     }
 
     @Test
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
index 879e105..33b931a 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
@@ -77,10 +77,9 @@
         return ExcludeFromSystemGestureNode(exclusion)
     }
 
-    override fun update(node: ExcludeFromSystemGestureNode): ExcludeFromSystemGestureNode =
-        node.also {
-            it.exclusion = exclusion
-        }
+    override fun update(node: ExcludeFromSystemGestureNode) {
+        node.exclusion = exclusion
+    }
 
     override fun hashCode(): Int {
         return exclusion.hashCode()
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/AndroidTextInputAdapter.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/AndroidTextInputAdapter.kt
index 1877cfa..47f6759 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/AndroidTextInputAdapter.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/AndroidTextInputAdapter.kt
@@ -26,7 +26,6 @@
 import android.view.View
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
-import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.text2.input.TextEditFilter
@@ -230,7 +229,7 @@
          * and grab the [InputConnection] to inject commands.
          */
         @TestOnly
-        @RestrictTo(RestrictTo.Scope.TESTS)
+        @VisibleForTesting
         fun setInputConnectionCreatedListenerForTests(
             listener: ((EditorInfo, InputConnection) -> Unit)?
         ) {
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/ComposeInputMethodManager.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/ComposeInputMethodManager.kt
index 71b3288..caccd1a 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/ComposeInputMethodManager.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/ComposeInputMethodManager.kt
@@ -24,7 +24,7 @@
 import android.view.inputmethod.ExtractedText
 import android.view.inputmethod.InputMethodManager
 import androidx.annotation.RequiresApi
-import androidx.annotation.RestrictTo
+import androidx.annotation.VisibleForTesting
 import androidx.core.view.SoftwareKeyboardControllerCompat
 import org.jetbrains.annotations.TestOnly
 
@@ -88,7 +88,7 @@
  * avoid breaking unrelated tests.
  */
 @TestOnly
-@RestrictTo(RestrictTo.Scope.TESTS)
+@VisibleForTesting
 internal fun overrideComposeInputMethodManagerFactoryForTests(
     factory: (View) -> ComposeInputMethodManager
 ): (View) -> ComposeInputMethodManager {
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldCoreModifier.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldCoreModifier.kt
index 655d496..15ab3ed 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldCoreModifier.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldCoreModifier.kt
@@ -90,7 +90,7 @@
         orientation = orientation,
     )
 
-    override fun update(node: TextFieldCoreModifierNode): TextFieldCoreModifierNode {
+    override fun update(node: TextFieldCoreModifierNode) {
         node.updateNode(
             isFocused = isFocused,
             textLayoutState = textLayoutState,
@@ -100,7 +100,6 @@
             scrollState = scrollState,
             orientation = orientation,
         )
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldDecoratorModifier.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldDecoratorModifier.kt
index e1546c6..1f81a01 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldDecoratorModifier.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/internal/TextFieldDecoratorModifier.kt
@@ -96,7 +96,7 @@
         singleLine = singleLine,
     )
 
-    override fun update(node: TextFieldDecoratorModifierNode): TextFieldDecoratorModifierNode {
+    override fun update(node: TextFieldDecoratorModifierNode) {
         node.updateNode(
             textFieldState = textFieldState,
             textLayoutState = textLayoutState,
@@ -108,7 +108,6 @@
             keyboardActions = keyboardActions,
             singleLine = singleLine,
         )
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt
index ab0b5f5..910e79f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt
@@ -104,12 +104,11 @@
         )
     }
 
-    override fun update(node: BackgroundNode): BackgroundNode {
+    override fun update(node: BackgroundNode) {
         node.color = color
         node.brush = brush
         node.alpha = alpha
         node.shape = shape
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
index 87d9b57..099246b 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
@@ -421,8 +421,8 @@
         onClick
     )
 
-    override fun update(node: ClickableNode) = node.also {
-        it.update(interactionSource, enabled, onClickLabel, role, onClick)
+    override fun update(node: ClickableNode) {
+        node.update(interactionSource, enabled, onClickLabel, role, onClick)
     }
 
     // Defined in the factory functions with inspectable
@@ -474,8 +474,8 @@
         onDoubleClick
     )
 
-    override fun update(node: CombinedClickableNode) = node.also {
-        it.update(
+    override fun update(node: CombinedClickableNode) {
+        node.update(
             interactionSource,
             enabled,
             onClickLabel,
@@ -757,8 +757,8 @@
         onClick = onClick
     )
 
-    override fun update(node: ClickableSemanticsNode) = node.also {
-        it.update(enabled, onClickLabel, role, onClick, onLongClickLabel, onLongClick)
+    override fun update(node: ClickableSemanticsNode) {
+        node.update(enabled, onClickLabel, role, onClick, onLongClickLabel, onLongClick)
     }
 
     override fun InspectorInfo.inspectableProperties() = Unit
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
index c909c05..bb1c694 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
@@ -137,7 +137,7 @@
     object : ModifierNodeElement<FocusableInNonTouchMode>() {
         override fun create(): FocusableInNonTouchMode = FocusableInNonTouchMode()
 
-        override fun update(node: FocusableInNonTouchMode): FocusableInNonTouchMode = node
+        override fun update(node: FocusableInNonTouchMode) {}
 
         override fun hashCode(): Int = System.identityHashCode(this)
 
@@ -168,8 +168,8 @@
     override fun create(): FocusableNode =
         FocusableNode(interactionSource)
 
-    override fun update(node: FocusableNode) = node.also {
-        it.update(interactionSource)
+    override fun update(node: FocusableNode) {
+        node.update(interactionSource)
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/FocusedBounds.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/FocusedBounds.kt
index adecbd5..5212dff 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/FocusedBounds.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/FocusedBounds.kt
@@ -51,8 +51,8 @@
 ) : ModifierNodeElement<FocusedBoundsObserverNode>() {
     override fun create(): FocusedBoundsObserverNode = FocusedBoundsObserverNode(onPositioned)
 
-    override fun update(node: FocusedBoundsObserverNode): FocusedBoundsObserverNode = node.also {
-        it.onPositioned = onPositioned
+    override fun update(node: FocusedBoundsObserverNode) {
+        node.onPositioned = onPositioned
     }
 
     override fun hashCode(): Int = onPositioned.hashCode()
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
index 4f2ae94..cfc7267 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
@@ -47,8 +47,8 @@
 ) : ModifierNodeElement<HoverableNode>() {
     override fun create() = HoverableNode(interactionSource)
 
-    override fun update(node: HoverableNode) = node.apply {
-        updateInteractionSource(interactionSource)
+    override fun update(node: HoverableNode) {
+        node.updateInteractionSource(interactionSource)
     }
 
     override fun hashCode(): Int {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
index 01fdca8..1d58733 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
@@ -338,10 +338,10 @@
         )
     }
 
-    override fun update(node: ScrollingLayoutNode): ScrollingLayoutNode = node.also {
-        it.scrollerState = scrollState
-        it.isReversed = isReversed
-        it.isVertical = isVertical
+    override fun update(node: ScrollingLayoutNode) {
+        node.scrollerState = scrollState
+        node.isReversed = isReversed
+        node.isVertical = isVertical
     }
 
     override fun hashCode(): Int {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
index 99bfce38..de09cb5 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
@@ -26,36 +26,37 @@
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.internal.JvmDefaultWithCompatibility
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.State
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.pointer.AwaitPointerEventScope
+import androidx.compose.ui.input.pointer.PointerEvent
 import androidx.compose.ui.input.pointer.PointerEventPass
 import androidx.compose.ui.input.pointer.PointerId
 import androidx.compose.ui.input.pointer.PointerInputChange
+import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
 import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.input.pointer.positionChange
 import androidx.compose.ui.input.pointer.positionChangeIgnoreConsumed
 import androidx.compose.ui.input.pointer.util.VelocityTracker
 import androidx.compose.ui.input.pointer.util.addPointerInputChange
-import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.node.DelegatingNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.PointerInputModifierNode
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.Velocity
 import kotlin.coroutines.cancellation.CancellationException
 import kotlin.math.sign
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.channels.SendChannel
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
 
 /**
  * State of [draggable]. Allows for a granular control of how deltas are consumed by the user as
@@ -183,7 +184,7 @@
     onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {},
     onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit = {},
     reverseDirection: Boolean = false
-): Modifier = draggable(
+): Modifier = this then DraggableElement(
     state = state,
     orientation = orientation,
     enabled = enabled,
@@ -195,18 +196,76 @@
     canDrag = { true }
 )
 
-internal fun Modifier.draggable(
-    state: DraggableState,
-    canDrag: (PointerInputChange) -> Boolean,
-    orientation: Orientation,
-    enabled: Boolean = true,
-    interactionSource: MutableInteractionSource? = null,
-    startDragImmediately: () -> Boolean,
-    onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {},
-    onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit = {},
-    reverseDirection: Boolean = false
-): Modifier = composed(
-    inspectorInfo = debugInspectorInfo {
+internal class DraggableElement(
+    private val state: DraggableState,
+    private val canDrag: (PointerInputChange) -> Boolean,
+    private val orientation: Orientation,
+    private val enabled: Boolean,
+    private val interactionSource: MutableInteractionSource?,
+    private val startDragImmediately: () -> Boolean,
+    private val onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
+    private val onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
+    private val reverseDirection: Boolean
+) : ModifierNodeElement<DraggableNode>() {
+    override fun create(): DraggableNode = DraggableNode(
+        state,
+        canDrag,
+        orientation,
+        enabled,
+        interactionSource,
+        startDragImmediately,
+        onDragStarted,
+        onDragStopped,
+        reverseDirection
+    )
+
+    override fun update(node: DraggableNode) {
+        node.update(
+            state,
+            canDrag,
+            orientation,
+            enabled,
+            interactionSource,
+            startDragImmediately,
+            onDragStarted,
+            onDragStopped,
+            reverseDirection
+        )
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as DraggableElement
+
+        if (state != other.state) return false
+        if (canDrag != other.canDrag) return false
+        if (orientation != other.orientation) return false
+        if (enabled != other.enabled) return false
+        if (interactionSource != other.interactionSource) return false
+        if (startDragImmediately != other.startDragImmediately) return false
+        if (onDragStarted != other.onDragStarted) return false
+        if (onDragStopped != other.onDragStopped) return false
+        if (reverseDirection != other.reverseDirection) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = state.hashCode()
+        result = 31 * result + canDrag.hashCode()
+        result = 31 * result + orientation.hashCode()
+        result = 31 * result + enabled.hashCode()
+        result = 31 * result + (interactionSource?.hashCode() ?: 0)
+        result = 31 * result + startDragImmediately.hashCode()
+        result = 31 * result + onDragStarted.hashCode()
+        result = 31 * result + onDragStopped.hashCode()
+        result = 31 * result + reverseDirection.hashCode()
+        return result
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
         name = "draggable"
         properties["canDrag"] = canDrag
         properties["orientation"] = orientation
@@ -218,56 +277,33 @@
         properties["onDragStopped"] = onDragStopped
         properties["state"] = state
     }
-) {
-    val draggedInteraction = remember { mutableStateOf<DragInteraction.Start?>(null) }
-    DisposableEffect(interactionSource) {
-        onDispose {
-            draggedInteraction.value?.let { interaction ->
-                interactionSource?.tryEmit(DragInteraction.Cancel(interaction))
-                draggedInteraction.value = null
-            }
-        }
-    }
-    val channel = remember { Channel<DragEvent>(capacity = Channel.UNLIMITED) }
-    val startImmediatelyState = rememberUpdatedState(startDragImmediately)
-    val canDragState = rememberUpdatedState(canDrag)
-    val dragLogic by rememberUpdatedState(
-        DragLogic(onDragStarted, onDragStopped, draggedInteraction, interactionSource)
-    )
-    LaunchedEffect(state) {
-        while (isActive) {
-            var event = channel.receive()
-            if (event !is DragStarted) continue
-            with(dragLogic) { processDragStart(event as DragStarted) }
-            try {
-                state.drag(MutatePriority.UserInput) {
-                    while (event !is DragStopped && event !is DragCancelled) {
-                        (event as? DragDelta)?.let { dragBy(it.delta.toFloat(orientation)) }
-                        event = channel.receive()
-                    }
-                }
-                with(dragLogic) {
-                    if (event is DragStopped) {
-                        processDragStop(event as DragStopped)
-                    } else if (event is DragCancelled) {
-                        processDragCancel()
-                    }
-                }
-            } catch (c: CancellationException) {
-                with(dragLogic) { processDragCancel() }
-            }
-        }
-    }
-    Modifier.pointerInput(state, orientation, enabled, reverseDirection) {
-        if (!enabled) return@pointerInput
+}
+
+internal class DraggableNode(
+    private var state: DraggableState,
+    private var canDrag: (PointerInputChange) -> Boolean,
+    private var orientation: Orientation,
+    private var enabled: Boolean,
+    private var interactionSource: MutableInteractionSource?,
+    private var startDragImmediately: () -> Boolean,
+    private var onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
+    private var onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
+    private var reverseDirection: Boolean
+) : DelegatingNode(), PointerInputModifierNode {
+    private val pointerInputNode = delegate(SuspendingPointerInputModifierNode {
+        // TODO: conditionally undelegate when aosp/2462416 lands?
+        if (!enabled) return@SuspendingPointerInputModifierNode
         coroutineScope {
             try {
                 awaitPointerEventScope {
                     while (isActive) {
                         val velocityTracker = VelocityTracker()
+                        @Suppress("UnnecessaryLambdaCreation")
                         awaitDownAndSlop(
-                            canDragState,
-                            startImmediatelyState,
+                            // Use lambdas here to make sure that if these properties are updated
+                            // while we suspend, we point to the new reference when we invoke them.
+                            { canDrag(it) },
+                            { startDragImmediately() },
                             velocityTracker,
                             orientation
                         )?.let {
@@ -303,20 +339,148 @@
                 }
             }
         }
+    })
+
+    private val channel = Channel<DragEvent>(capacity = Channel.UNLIMITED)
+    private var observeChannelJob: Job? = null
+    private var dragInteraction: DragInteraction.Start? = null
+
+    override fun onAttach() {
+        observeChannel()
+    }
+
+    override fun onDetach() {
+        disposeInteractionSource()
+    }
+
+    override fun onPointerEvent(
+        pointerEvent: PointerEvent,
+        pass: PointerEventPass,
+        bounds: IntSize
+    ) {
+        pointerInputNode.onPointerEvent(pointerEvent, pass, bounds)
+    }
+
+    override fun onCancelPointerInput() {
+        pointerInputNode.onCancelPointerInput()
+    }
+
+    fun update(
+        state: DraggableState,
+        canDrag: (PointerInputChange) -> Boolean,
+        orientation: Orientation,
+        enabled: Boolean,
+        interactionSource: MutableInteractionSource?,
+        startDragImmediately: () -> Boolean,
+        onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
+        onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
+        reverseDirection: Boolean
+    ) {
+        var resetPointerInputHandling = false
+        if (this.state != state) {
+            // Reset observation when the state changes
+            observeChannel()
+            this.state = state
+        }
+        this.canDrag = canDrag
+        if (this.orientation != orientation) {
+            this.orientation = orientation
+            resetPointerInputHandling = true
+        }
+        if (this.enabled != enabled) {
+            this.enabled = enabled
+            if (!enabled) {
+                disposeInteractionSource()
+            }
+            resetPointerInputHandling = true
+        }
+        if (this.interactionSource != interactionSource) {
+            disposeInteractionSource()
+            this.interactionSource = interactionSource
+        }
+        this.startDragImmediately = startDragImmediately
+        this.onDragStarted = onDragStarted
+        this.onDragStopped = onDragStopped
+        if (this.reverseDirection != reverseDirection) {
+            this.reverseDirection = reverseDirection
+            resetPointerInputHandling = true
+        }
+        if (resetPointerInputHandling) {
+            pointerInputNode.resetPointerInputHandler()
+        }
+    }
+
+    private fun observeChannel() {
+        observeChannelJob?.cancel()
+        observeChannelJob = coroutineScope.launch {
+            while (isActive) {
+                var event = channel.receive()
+                if (event !is DragStarted) continue
+                processDragStart(event)
+                try {
+                    state.drag(MutatePriority.UserInput) {
+                        while (event !is DragStopped && event !is DragCancelled) {
+                            (event as? DragDelta)?.let { dragBy(it.delta.toFloat(orientation)) }
+                            event = channel.receive()
+                        }
+                    }
+                    if (event is DragStopped) {
+                        processDragStop(event as DragStopped)
+                    } else if (event is DragCancelled) {
+                        processDragCancel()
+                    }
+                } catch (c: CancellationException) {
+                    processDragCancel()
+                }
+            }
+        }
+    }
+
+    private suspend fun CoroutineScope.processDragStart(event: DragStarted) {
+        dragInteraction?.let { oldInteraction ->
+            interactionSource?.emit(DragInteraction.Cancel(oldInteraction))
+        }
+        val interaction = DragInteraction.Start()
+        interactionSource?.emit(interaction)
+        dragInteraction = interaction
+        onDragStarted.invoke(this, event.startPoint)
+    }
+
+    private suspend fun CoroutineScope.processDragStop(event: DragStopped) {
+        dragInteraction?.let { interaction ->
+            interactionSource?.emit(DragInteraction.Stop(interaction))
+            dragInteraction = null
+        }
+        onDragStopped.invoke(this, event.velocity)
+    }
+
+    private suspend fun CoroutineScope.processDragCancel() {
+        dragInteraction?.let { interaction ->
+            interactionSource?.emit(DragInteraction.Cancel(interaction))
+            dragInteraction = null
+        }
+        onDragStopped.invoke(this, Velocity.Zero)
+    }
+
+    private fun disposeInteractionSource() {
+        dragInteraction?.let { interaction ->
+            interactionSource?.tryEmit(DragInteraction.Cancel(interaction))
+            dragInteraction = null
+        }
     }
 }
 
 private suspend fun AwaitPointerEventScope.awaitDownAndSlop(
-    canDrag: State<(PointerInputChange) -> Boolean>,
-    startDragImmediately: State<() -> Boolean>,
+    canDrag: (PointerInputChange) -> Boolean,
+    startDragImmediately: () -> Boolean,
     velocityTracker: VelocityTracker,
     orientation: Orientation
 ): Pair<PointerInputChange, Offset>? {
     val initialDown =
         awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
-    return if (!canDrag.value.invoke(initialDown)) {
+    return if (!canDrag(initialDown)) {
         null
-    } else if (startDragImmediately.value.invoke()) {
+    } else if (startDragImmediately()) {
         initialDown.consume()
         velocityTracker.addPointerInputChange(initialDown)
         // since we start immediately we don't wait for slop and the initial delta is 0
@@ -392,40 +556,6 @@
     )?.let(onDrag) != null
 }
 
-private class DragLogic(
-    val onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
-    val onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
-    val dragStartInteraction: MutableState<DragInteraction.Start?>,
-    val interactionSource: MutableInteractionSource?
-) {
-
-    suspend fun CoroutineScope.processDragStart(event: DragStarted) {
-        dragStartInteraction.value?.let { oldInteraction ->
-            interactionSource?.emit(DragInteraction.Cancel(oldInteraction))
-        }
-        val interaction = DragInteraction.Start()
-        interactionSource?.emit(interaction)
-        dragStartInteraction.value = interaction
-        onDragStarted.invoke(this, event.startPoint)
-    }
-
-    suspend fun CoroutineScope.processDragStop(event: DragStopped) {
-        dragStartInteraction.value?.let { interaction ->
-            interactionSource?.emit(DragInteraction.Stop(interaction))
-            dragStartInteraction.value = null
-        }
-        onDragStopped.invoke(this, event.velocity)
-    }
-
-    suspend fun CoroutineScope.processDragCancel() {
-        dragStartInteraction.value?.let { interaction ->
-            interactionSource?.emit(DragInteraction.Cancel(interaction))
-            dragStartInteraction.value = null
-        }
-        onDragStopped.invoke(this, Velocity.Zero)
-    }
-}
-
 private class DefaultDraggableState(val onDelta: (Float) -> Unit) : DraggableState {
 
     private val dragScope: DragScope = object : DragScope {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
index 495b68f..c387135 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
@@ -64,6 +64,7 @@
 import androidx.compose.ui.util.fastAll
 import androidx.compose.ui.util.fastForEach
 import kotlin.math.abs
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
@@ -271,24 +272,29 @@
     val draggableState = remember { ScrollDraggableState(scrollLogic) }
     val scrollConfig = platformScrollConfig()
 
-    return draggable(
-        draggableState,
-        orientation = orientation,
-        enabled = enabled,
-        interactionSource = interactionSource,
-        reverseDirection = false,
-        startDragImmediately = { scrollLogic.value.shouldScrollImmediately() },
-        onDragStopped = { velocity ->
-            nestedScrollDispatcher.value.coroutineScope.launch {
-                scrollLogic.value.onDragStopped(velocity)
-            }
-        },
-        canDrag = { down -> down.type != PointerType.Mouse }
-    )
+    return this
+        .then(DraggableElement(
+            state = draggableState,
+            orientation = orientation,
+            enabled = enabled,
+            interactionSource = interactionSource,
+            reverseDirection = false,
+            startDragImmediately = { scrollLogic.value.shouldScrollImmediately() },
+            onDragStarted = NoOpOnDragStarted,
+            onDragStopped = { velocity ->
+                nestedScrollDispatcher.value.coroutineScope.launch {
+                    scrollLogic.value.onDragStopped(velocity)
+                }
+            },
+            canDrag = { down -> down.type != PointerType.Mouse }
+        ))
         .then(MouseWheelScrollElement(scrollLogic, scrollConfig))
         .nestedScroll(nestedScrollConnection, nestedScrollDispatcher.value)
 }
 
+// {} isn't being memoized for us, so extract this to make sure we compare equally on recomposition.
+private val NoOpOnDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {}
+
 private class MouseWheelScrollElement(
     val scrollingLogicState: State<ScrollingLogic>,
     val mouseWheelScrollConfig: ScrollConfig
@@ -297,9 +303,9 @@
         return MouseWheelScrollNode(scrollingLogicState, mouseWheelScrollConfig)
     }
 
-    override fun update(node: MouseWheelScrollNode): MouseWheelScrollNode = node.also {
-        it.scrollingLogicState = scrollingLogicState
-        it.mouseWheelScrollConfig = mouseWheelScrollConfig
+    override fun update(node: MouseWheelScrollNode) {
+        node.scrollingLogicState = scrollingLogicState
+        node.mouseWheelScrollConfig = mouseWheelScrollConfig
     }
 
     override fun hashCode(): Int {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnapLayoutInfoProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyGridSnapLayoutInfoProvider.kt
similarity index 60%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnapLayoutInfoProvider.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyGridSnapLayoutInfoProvider.kt
index e649842..515dfc3 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/snapping/LazyGridSnapLayoutInfoProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyGridSnapLayoutInfoProvider.kt
@@ -14,33 +14,55 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.demos.snapping
+package androidx.compose.foundation.gestures.snapping
 
+import androidx.compose.animation.core.DecayAnimationSpec
+import androidx.compose.animation.core.calculateTargetValue
+import androidx.compose.animation.splineBasedDecay
 import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.fastFilter
 import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
 import androidx.compose.foundation.lazy.grid.LazyGridItemInfo
 import androidx.compose.foundation.lazy.grid.LazyGridLayoutInfo
 import androidx.compose.foundation.lazy.grid.LazyGridState
 import androidx.compose.ui.unit.Density
+import androidx.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastSumBy
+import kotlin.math.absoluteValue
 import kotlin.math.sign
-import kotlin.math.abs
 
-@OptIn(ExperimentalFoundationApi::class)
+/**
+ * A [SnapLayoutInfoProvider] for LazyGrids.
+ *
+ * @param lazyGridState The [LazyGridState] with information about the current state of the grid
+ * @param positionInLayout The desired positioning of the snapped item within the main layout.
+ * This position should be considered with regards to the start edge of the item and the placement
+ * within the viewport.
+ *
+ * @return A [SnapLayoutInfoProvider] that can be used with [SnapFlingBehavior]
+ */
+@ExperimentalFoundationApi
 fun SnapLayoutInfoProvider(
     lazyGridState: LazyGridState,
-    positionInLayout: (Float, Float) -> Float = { mainAxisLayoutSize, mainAxisItemSize ->
-        mainAxisLayoutSize / 2f - mainAxisItemSize / 2f
-    }
+    positionInLayout: SnapPositionInLayout = SnapPositionInLayout.CenterToCenter
 ) = object : SnapLayoutInfoProvider {
     private val layoutInfo: LazyGridLayoutInfo
         get() = lazyGridState.layoutInfo
 
-    override fun Density.calculateApproachOffset(initialVelocity: Float) = 0f
+    override fun Density.calculateApproachOffset(initialVelocity: Float): Float {
+        val decayAnimationSpec: DecayAnimationSpec<Float> = splineBasedDecay(this)
+        val offset =
+            decayAnimationSpec.calculateTargetValue(NoDistance, initialVelocity).absoluteValue
+        val finalDecayOffset = (offset - calculateSnapStepSize()).coerceAtLeast(0f)
+        return if (finalDecayOffset == 0f) {
+            finalDecayOffset
+        } else {
+            finalDecayOffset * initialVelocity.sign
+        }
+    }
 
-    // use the first row/column as a baseline for snapping.
     private val singleAxisItems: List<LazyGridItemInfo>
-        get() = lazyGridState.layoutInfo.visibleItemsInfo.filter {
+        get() = lazyGridState.layoutInfo.visibleItemsInfo.fastFilter {
             if (lazyGridState.layoutInfo.orientation == Orientation.Horizontal) {
                 it.row == 0
             } else {
@@ -54,7 +76,7 @@
         var distanceFromItemBeforeTarget = Float.NEGATIVE_INFINITY
         var distanceFromItemAfterTarget = Float.POSITIVE_INFINITY
 
-        layoutInfo.visibleItemsInfo.forEach { item ->
+        layoutInfo.visibleItemsInfo.fastForEach { item ->
             val distance =
                 calculateDistanceToDesiredSnapPosition(layoutInfo, item, positionInLayout)
 
@@ -79,9 +101,9 @@
     override fun Density.calculateSnapStepSize(): Float {
         return if (singleAxisItems.isNotEmpty()) {
             val size = if (layoutInfo.orientation == Orientation.Vertical) {
-                singleAxisItems.sumOf { it.size.height }
+                singleAxisItems.fastSumBy { it.size.height }
             } else {
-                singleAxisItems.sumOf { it.size.width }
+                singleAxisItems.fastSumBy { it.size.width }
             }
             size / singleAxisItems.size.toFloat()
         } else {
@@ -90,68 +112,43 @@
     }
 }
 
-internal fun calculateDistanceToDesiredSnapPosition(
+@OptIn(ExperimentalFoundationApi::class)
+internal fun Density.calculateDistanceToDesiredSnapPosition(
     layoutInfo: LazyGridLayoutInfo,
     item: LazyGridItemInfo,
-    positionInLayout: (layoutSize: Float, itemSize: Float) -> Float
+    positionInLayout: SnapPositionInLayout = SnapPositionInLayout.CenterToCenter
 ): Float {
 
     val containerSize =
         with(layoutInfo) { singleAxisViewportSize - beforeContentPadding - afterContentPadding }
 
-    val desiredDistance =
-        positionInLayout(containerSize, item.sizeOnMainAxis(layoutInfo.orientation))
+    val desiredDistance = with(positionInLayout) {
+        position(containerSize, item.sizeOnMainAxis(layoutInfo.orientation), item.index)
+    }
 
     val itemCurrentPosition = item.offsetOnMainAxis(layoutInfo.orientation)
-    return itemCurrentPosition - desiredDistance
+    return itemCurrentPosition - desiredDistance.toFloat()
 }
 
-private val LazyGridLayoutInfo.singleAxisViewportSize: Float
+private val LazyGridLayoutInfo.singleAxisViewportSize: Int
     get() = if (orientation == Orientation.Vertical) {
-        viewportSize.height.toFloat()
+        viewportSize.height
     } else {
-        viewportSize.width.toFloat()
+        viewportSize.width
     }
 
-private fun LazyGridItemInfo.sizeOnMainAxis(orientation: Orientation): Float {
+private fun LazyGridItemInfo.sizeOnMainAxis(orientation: Orientation): Int {
     return if (orientation == Orientation.Vertical) {
-        size.height.toFloat()
+        size.height
     } else {
-        size.width.toFloat()
+        size.width
     }
 }
 
-private fun LazyGridItemInfo.offsetOnMainAxis(orientation: Orientation): Float {
+private fun LazyGridItemInfo.offsetOnMainAxis(orientation: Orientation): Int {
     return if (orientation == Orientation.Vertical) {
-        offset.y.toFloat()
+        offset.y
     } else {
-        offset.x.toFloat()
-    }
-}
-
-internal fun calculateFinalOffset(velocity: Float, lowerBound: Float, upperBound: Float): Float {
-
-    fun Float.isValidDistance(): Boolean {
-        return this != Float.POSITIVE_INFINITY && this != Float.NEGATIVE_INFINITY
-    }
-
-    val finalDistance = when (sign(velocity)) {
-        0f -> {
-            if (abs(upperBound) <= abs(lowerBound)) {
-                upperBound
-            } else {
-                lowerBound
-            }
-        }
-
-        1f -> upperBound
-        -1f -> lowerBound
-        else -> 0f
-    }
-
-    return if (finalDistance.isValidDistance()) {
-        finalDistance
-    } else {
-        0f
+        offset.x
     }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyListSnapLayoutInfoProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyListSnapLayoutInfoProvider.kt
index 093ec01..fece172 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyListSnapLayoutInfoProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/LazyListSnapLayoutInfoProvider.kt
@@ -46,8 +46,7 @@
 @ExperimentalFoundationApi
 fun SnapLayoutInfoProvider(
     lazyListState: LazyListState,
-    positionInLayout: Density.(layoutSize: Float, itemSize: Float) -> Float =
-        { layoutSize, itemSize -> (layoutSize / 2f - itemSize / 2f) }
+    positionInLayout: SnapPositionInLayout = SnapPositionInLayout.CenterToCenter
 ): SnapLayoutInfoProvider = object : SnapLayoutInfoProvider {
 
     private val layoutInfo: LazyListLayoutInfo
@@ -111,16 +110,18 @@
     return rememberSnapFlingBehavior(snappingLayout)
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 internal fun Density.calculateDistanceToDesiredSnapPosition(
     layoutInfo: LazyListLayoutInfo,
     item: LazyListItemInfo,
-    positionInLayout: Density.(layoutSize: Float, itemSize: Float) -> Float
+    positionInLayout: SnapPositionInLayout
 ): Float {
     val containerSize =
         with(layoutInfo) { singleAxisViewportSize - beforeContentPadding - afterContentPadding }
 
-    val desiredDistance =
-        positionInLayout(containerSize.toFloat(), item.size.toFloat())
+    val desiredDistance = with(positionInLayout) {
+        position(containerSize, item.size, item.index)
+    }.toFloat()
 
     val itemCurrentPosition = item.offset
     return itemCurrentPosition - desiredDistance
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapPositionInLayout.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapPositionInLayout.kt
new file mode 100644
index 0000000..3b3f94f
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapPositionInLayout.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.compose.foundation.gestures.snapping
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.ui.unit.Density
+
+/**
+ * Describes the general positioning of a given snap item in its containing layout.
+ */
+@ExperimentalFoundationApi
+fun interface SnapPositionInLayout {
+    /**
+     * Calculates an offset positioning between a container and an element within this container.
+     * The offset calculation is the necessary diff that should be applied to the item offset to
+     * align the item with a position within the container. As a base line, if we wanted to align
+     * the start of the container and the start of the item, we would return 0 in this function.
+     */
+    fun Density.position(layoutSize: Int, itemSize: Int, itemIndex: Int): Int
+
+    companion object {
+        /**
+         * Aligns the center of the item with the center of the containing layout.
+         */
+        val CenterToCenter =
+            SnapPositionInLayout { layoutSize, itemSize, _ -> layoutSize / 2 - itemSize / 2 }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScopeImpl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScopeImpl.kt
index 0734088..16639c9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScopeImpl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScopeImpl.kt
@@ -89,10 +89,10 @@
         )
     }
 
-    override fun update(node: ParentSizeNode): ParentSizeNode = node.also {
-        it.fraction = fraction
-        it.widthState = widthState
-        it.heightState = heightState
+    override fun update(node: ParentSizeNode) {
+        node.fraction = fraction
+        node.widthState = widthState
+        node.heightState = heightState
     }
 
     override fun equals(other: Any?): Boolean {
@@ -160,8 +160,8 @@
 
     override fun create(): AnimateItemPlacementNode = AnimateItemPlacementNode(animationSpec)
 
-    override fun update(node: AnimateItemPlacementNode): AnimateItemPlacementNode = node.also {
-        it.delegatingNode.placementAnimationSpec = animationSpec
+    override fun update(node: AnimateItemPlacementNode) {
+        node.delegatingNode.placementAnimationSpec = animationSpec
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListAnimateScrollScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListAnimateScrollScope.kt
index c048b9b..24e8bd2 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListAnimateScrollScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListAnimateScrollScope.kt
@@ -50,8 +50,10 @@
     }
 
     override fun expectedDistanceTo(index: Int, targetScrollOffset: Int): Float {
-        val visibleItems = state.layoutInfo.visibleItemsInfo
-        val averageSize = visibleItems.fastSumBy { it.size } / visibleItems.size
+        val layoutInfo = state.layoutInfo
+        val visibleItems = layoutInfo.visibleItemsInfo
+        val averageSize =
+            visibleItems.fastSumBy { it.size } / visibleItems.size + layoutInfo.mainAxisItemSpacing
         val indexesDiff = index - firstVisibleItemIndex
         var coercedOffset = minOf(abs(targetScrollOffset), averageSize)
         if (targetScrollOffset < 0) coercedOffset *= -1
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt
index 6e1f924..15ebac4 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt
@@ -102,11 +102,9 @@
                         )
                     }
                 } else {
-                    repeat(item.placeablesCount) { placeableIndex ->
-                        item.getParentData(placeableIndex).node?.apply {
-                            if (rawOffset != LazyLayoutAnimateItemModifierNode.NotInitialized) {
-                                rawOffset += scrollOffset
-                            }
+                    item.forEachNode { _, node ->
+                        if (node.rawOffset != LazyLayoutAnimateItemModifierNode.NotInitialized) {
+                            node.rawOffset += scrollOffset
                         }
                     }
                     startAnimationsIfNeeded(item)
@@ -117,19 +115,19 @@
             }
         }
 
-        var currentMainAxisOffset = 0
+        var accumulatedOffset = 0
         movingInFromStartBound.sortByDescending { previousKeyToIndexMap[it.key] }
         movingInFromStartBound.fastForEach { item ->
-            val mainAxisOffset = 0 - currentMainAxisOffset - item.size
-            currentMainAxisOffset += item.size
+            accumulatedOffset += item.size
+            val mainAxisOffset = 0 - accumulatedOffset
             initializeNode(item, mainAxisOffset)
             startAnimationsIfNeeded(item)
         }
-        currentMainAxisOffset = 0
+        accumulatedOffset = 0
         movingInFromEndBound.sortBy { previousKeyToIndexMap[it.key] }
         movingInFromEndBound.fastForEach { item ->
-            val mainAxisOffset = mainAxisLayoutSize + currentMainAxisOffset
-            currentMainAxisOffset += item.size
+            val mainAxisOffset = mainAxisLayoutSize + accumulatedOffset
+            accumulatedOffset += item.size
             initializeNode(item, mainAxisOffset)
             startAnimationsIfNeeded(item)
         }
@@ -163,21 +161,21 @@
             }
         }
 
-        currentMainAxisOffset = 0
+        accumulatedOffset = 0
         movingAwayToStartBound.sortByDescending { keyToIndexMap[it.key] }
         movingAwayToStartBound.fastForEach { item ->
-            val mainAxisOffset = 0 - currentMainAxisOffset - item.size
-            currentMainAxisOffset += item.size
+            accumulatedOffset += item.size
+            val mainAxisOffset = 0 - accumulatedOffset
 
             val positionedItem = item.position(mainAxisOffset, layoutWidth, layoutHeight)
             positionedItems.add(positionedItem)
             startAnimationsIfNeeded(positionedItem)
         }
-        currentMainAxisOffset = 0
+        accumulatedOffset = 0
         movingAwayToEndBound.sortBy { keyToIndexMap[it.key] }
         movingAwayToEndBound.fastForEach { item ->
-            val mainAxisOffset = mainAxisLayoutSize + currentMainAxisOffset
-            currentMainAxisOffset += item.size
+            val mainAxisOffset = mainAxisLayoutSize + accumulatedOffset
+            accumulatedOffset += item.size
 
             val positionedItem = item.position(mainAxisOffset, layoutWidth, layoutHeight)
             positionedItems.add(positionedItem)
@@ -214,29 +212,23 @@
         }
 
         // initialize offsets
-        repeat(item.placeablesCount) { placeableIndex ->
-            val node = item.getParentData(placeableIndex).node
-            if (node != null) {
-                val diffToFirstPlaceableOffset =
-                    item.getOffset(placeableIndex) - firstPlaceableOffset
-                node.rawOffset = targetFirstPlaceableOffset + diffToFirstPlaceableOffset
-            }
+        item.forEachNode { placeableIndex, node ->
+            val diffToFirstPlaceableOffset =
+                item.getOffset(placeableIndex) - firstPlaceableOffset
+            node.rawOffset = targetFirstPlaceableOffset + diffToFirstPlaceableOffset
         }
     }
 
     private fun startAnimationsIfNeeded(item: LazyListPositionedItem) {
-        repeat(item.placeablesCount) { placeableIndex ->
-            val node = item.getParentData(placeableIndex).node
-            if (node != null) {
-                val newTarget = item.getOffset(placeableIndex)
-                val currentTarget = node.rawOffset
-                if (currentTarget == LazyLayoutAnimateItemModifierNode.NotInitialized) {
-                    node.rawOffset = newTarget
-                } else if (currentTarget != newTarget) {
-                    node.rawOffset = newTarget
-                    node.animatePlacementDelta(newTarget - currentTarget)
-                }
+        item.forEachNode { placeableIndex, node ->
+            val newTarget = item.getOffset(placeableIndex)
+            val currentTarget = node.rawOffset
+            if (currentTarget != LazyLayoutAnimateItemModifierNode.NotInitialized &&
+                currentTarget != newTarget
+            ) {
+                node.animatePlacementDelta(newTarget - currentTarget)
             }
+            node.rawOffset = newTarget
         }
     }
 
@@ -244,11 +236,15 @@
 
     private val LazyListPositionedItem.hasAnimations: Boolean
         get() {
-            repeat(placeablesCount) { index ->
-                if (getParentData(index).node != null) {
-                    return true
-                }
-            }
+            forEachNode { _, _ -> return true }
             return false
         }
+
+    private inline fun LazyListPositionedItem.forEachNode(
+        block: (placeableIndex: Int, node: LazyLayoutAnimateItemModifierNode) -> Unit
+    ) {
+        repeat(placeablesCount) { index ->
+            getParentData(index).node?.let { block(index, it) }
+        }
+    }
 }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateScrollScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateScrollScope.kt
index 174036d..b29a04f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateScrollScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridAnimateScrollScope.kt
@@ -54,10 +54,9 @@
     }
 
     override fun expectedDistanceTo(index: Int, targetScrollOffset: Int): Float {
-        val visibleItems = state.layoutInfo.visibleItemsInfo
         val slotsPerLine = state.slotsPerLine
         val averageLineMainAxisSize = calculateLineAverageMainAxisSize(
-            visibleItems,
+            state.layoutInfo,
             state.isVertical
         )
         val before = index < firstVisibleItemIndex
@@ -74,9 +73,10 @@
     override val numOfItemsForTeleport: Int get() = 100 * state.slotsPerLine
 
     private fun calculateLineAverageMainAxisSize(
-        visibleItems: List<LazyGridItemInfo>,
+        layoutInfo: LazyGridLayoutInfo,
         isVertical: Boolean
     ): Int {
+        val visibleItems = layoutInfo.visibleItemsInfo
         val lineOf: (Int) -> Int = {
             if (isVertical) visibleItems[it].row else visibleItems[it].column
         }
@@ -113,7 +113,7 @@
             lineStartIndex = lineEndIndex
         }
 
-        return totalLinesMainAxisSize / linesCount
+        return totalLinesMainAxisSize / linesCount + layoutInfo.mainAxisItemSpacing
     }
 
     override suspend fun scroll(block: suspend ScrollScope.() -> Unit) {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridDsl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridDsl.kt
index 5492a12..f54d52e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridDsl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridDsl.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.foundation.lazy.grid
 
-import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.FlingBehavior
 import androidx.compose.foundation.gestures.ScrollableDefaults
 import androidx.compose.foundation.layout.Arrangement
@@ -327,7 +326,6 @@
      * If the screen is 88.dp wide tne there will be 4 columns 20.dp each with remaining 8.dp
      * distributed through [Arrangement.Horizontal].
      */
-    @ExperimentalFoundationApi
     class FixedSize(private val size: Dp) : GridCells {
         init {
             require(size > 0.dp) { "Provided size $size should be larger than zero." }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemPlacementAnimator.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemPlacementAnimator.kt
index 5bdc836..2f36dec 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemPlacementAnimator.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemPlacementAnimator.kt
@@ -107,11 +107,9 @@
                         )
                     }
                 } else {
-                    repeat(item.placeablesCount) { placeableIndex ->
-                        item.getParentData(placeableIndex).node?.apply {
-                            if (rawOffset != LazyLayoutAnimateItemModifierNode.NotInitialized) {
-                                rawOffset += scrollOffset
-                            }
+                    item.forEachNode {
+                        if (it.rawOffset != LazyLayoutAnimateItemModifierNode.NotInitialized) {
+                            it.rawOffset += scrollOffset
                         }
                     }
                     itemInfo.crossAxisSize = item.getCrossAxisSize()
@@ -124,7 +122,7 @@
             }
         }
 
-        var currentMainAxisOffset = 0
+        var accumulatedOffset = 0
         var previousLine = -1
         var previousLineMainAxisSize = 0
         movingInFromStartBound.sortByDescending { previousKeyToIndexMap[it.key] }
@@ -133,15 +131,15 @@
             if (line != -1 && line == previousLine) {
                 previousLineMainAxisSize = maxOf(previousLineMainAxisSize, item.getMainAxisSize())
             } else {
-                currentMainAxisOffset += previousLineMainAxisSize
+                accumulatedOffset += previousLineMainAxisSize
                 previousLineMainAxisSize = item.getMainAxisSize()
                 previousLine = line
             }
-            val mainAxisOffset = 0 - currentMainAxisOffset - item.getMainAxisSize()
+            val mainAxisOffset = 0 - accumulatedOffset - item.getMainAxisSize()
             initializeNode(item, mainAxisOffset)
             startAnimationsIfNeeded(item)
         }
-        currentMainAxisOffset = 0
+        accumulatedOffset = 0
         previousLine = -1
         previousLineMainAxisSize = 0
         movingInFromEndBound.sortBy { previousKeyToIndexMap[it.key] }
@@ -150,11 +148,11 @@
             if (line != -1 && line == previousLine) {
                 previousLineMainAxisSize = maxOf(previousLineMainAxisSize, item.getMainAxisSize())
             } else {
-                currentMainAxisOffset += previousLineMainAxisSize
+                accumulatedOffset += previousLineMainAxisSize
                 previousLineMainAxisSize = item.getMainAxisSize()
                 previousLine = line
             }
-            val mainAxisOffset = mainAxisLayoutSize + currentMainAxisOffset
+            val mainAxisOffset = mainAxisLayoutSize + accumulatedOffset
             initializeNode(item, mainAxisOffset)
             startAnimationsIfNeeded(item)
         }
@@ -196,7 +194,7 @@
             }
         }
 
-        currentMainAxisOffset = 0
+        accumulatedOffset = 0
         previousLine = -1
         previousLineMainAxisSize = 0
         movingAwayToStartBound.sortByDescending { keyToIndexMap[it.key] }
@@ -205,11 +203,11 @@
             if (line != -1 && line == previousLine) {
                 previousLineMainAxisSize = maxOf(previousLineMainAxisSize, item.mainAxisSize)
             } else {
-                currentMainAxisOffset += previousLineMainAxisSize
+                accumulatedOffset += previousLineMainAxisSize
                 previousLineMainAxisSize = item.mainAxisSize
                 previousLine = line
             }
-            val mainAxisOffset = 0 - currentMainAxisOffset - item.mainAxisSize
+            val mainAxisOffset = 0 - accumulatedOffset - item.mainAxisSize
 
             val itemInfo = keyToItemInfoMap.getValue(item.key)
 
@@ -224,7 +222,7 @@
             positionedItems.add(positionedItem)
             startAnimationsIfNeeded(positionedItem)
         }
-        currentMainAxisOffset = 0
+        accumulatedOffset = 0
         previousLine = -1
         previousLineMainAxisSize = 0
         movingAwayToEndBound.sortBy { keyToIndexMap[it.key] }
@@ -233,11 +231,11 @@
             if (line != -1 && line == previousLine) {
                 previousLineMainAxisSize = maxOf(previousLineMainAxisSize, item.mainAxisSize)
             } else {
-                currentMainAxisOffset += previousLineMainAxisSize
+                accumulatedOffset += previousLineMainAxisSize
                 previousLineMainAxisSize = item.mainAxisSize
                 previousLine = line
             }
-            val mainAxisOffset = mainAxisLayoutSize + currentMainAxisOffset
+            val mainAxisOffset = mainAxisLayoutSize + accumulatedOffset
 
             val itemInfo = keyToItemInfoMap.getValue(item.key)
             val positionedItem = item.position(
@@ -283,29 +281,23 @@
         }
 
         // initialize offsets
-        repeat(item.placeablesCount) { placeableIndex ->
-            val node = item.getParentData(placeableIndex).node
-            if (node != null) {
-                val diffToFirstPlaceableOffset =
-                    item.offset - firstPlaceableOffset
-                node.rawOffset = targetFirstPlaceableOffset + diffToFirstPlaceableOffset
-            }
+        item.forEachNode { node ->
+            val diffToFirstPlaceableOffset =
+                item.offset - firstPlaceableOffset
+            node.rawOffset = targetFirstPlaceableOffset + diffToFirstPlaceableOffset
         }
     }
 
     private fun startAnimationsIfNeeded(item: LazyGridPositionedItem) {
-        repeat(item.placeablesCount) { placeableIndex ->
-            val node = item.getParentData(placeableIndex).node
-            if (node != null) {
-                val newTarget = item.offset
-                val currentTarget = node.rawOffset
-                if (currentTarget == LazyLayoutAnimateItemModifierNode.NotInitialized) {
-                    node.rawOffset = item.offset
-                } else if (currentTarget != newTarget) {
-                    node.rawOffset = newTarget
-                    node.animatePlacementDelta(item.offset - currentTarget)
-                }
+        item.forEachNode { node ->
+            val newTarget = item.offset
+            val currentTarget = node.rawOffset
+            if (currentTarget != LazyLayoutAnimateItemModifierNode.NotInitialized &&
+                currentTarget != newTarget
+            ) {
+                node.animatePlacementDelta(newTarget - currentTarget)
             }
+            node.rawOffset = newTarget
         }
     }
 
@@ -313,13 +305,17 @@
 
     private val LazyGridPositionedItem.hasAnimations: Boolean
         get() {
-            repeat(placeablesCount) { index ->
-                if (getParentData(index).node != null) {
-                    return true
-                }
-            }
+            forEachNode { return true }
             return false
         }
+
+    private inline fun LazyGridPositionedItem.forEachNode(
+        block: (LazyLayoutAnimateItemModifierNode) -> Unit
+    ) {
+        repeat(placeablesCount) { index ->
+            getParentData(index).node?.let(block)
+        }
+    }
 }
 
 private class ItemInfo(
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScope.kt
index 794b9216..208ee3f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScope.kt
@@ -36,7 +36,7 @@
      *
      * When you provide a key via [LazyGridScope.item]/[LazyGridScope.items] this modifier will
      * enable item reordering animations. Aside from item reordering all other position changes
-     * caused by events like arrangement or alignment changes will also be animated.
+     * caused by events like arrangement changes will also be animated.
      *
      * @param animationSpec a finite animation that will be used to animate the item placement.
      */
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScopeImpl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScopeImpl.kt
index 7e28d2f..09fb209 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScopeImpl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemScopeImpl.kt
@@ -40,8 +40,8 @@
 
     override fun create(): AnimateItemPlacementNode = AnimateItemPlacementNode(animationSpec)
 
-    override fun update(node: AnimateItemPlacementNode): AnimateItemPlacementNode = node.also {
-        it.delegatingNode.placementAnimationSpec = animationSpec
+    override fun update(node: AnimateItemPlacementNode) {
+        node.delegatingNode.placementAnimationSpec = animationSpec
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasure.kt
index 8e43db2..a2a11fe 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasure.kt
@@ -423,6 +423,6 @@
         crossAxisOffset = 0,
         layoutWidth = layoutWidth,
         layoutHeight = layoutHeight,
-        row = 0,
-        column = 0
+        row = -1,
+        column = -1
     )
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyAnimateScroll.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyAnimateScroll.kt
index 3548bcd..78fd421 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyAnimateScroll.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyAnimateScroll.kt
@@ -208,7 +208,11 @@
                     // We don't throw ItemFoundInScroll when we snap, because once we've snapped to
                     // the final position, there's no need to animate to it.
                     if (isOvershot()) {
-                        debugLog { "Overshot" }
+                        debugLog {
+                            "Overshot, " +
+                                "item $firstVisibleItemIndex at $firstVisibleItemScrollOffset, " +
+                                "target is $scrollOffset"
+                        }
                         snapToItem(index = index, scrollOffset = scrollOffset)
                         loop = false
                         cancelAnimation()
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateScrollScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateScrollScope.kt
index 57f75d2..eb7fc8c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateScrollScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridAnimateScrollScope.kt
@@ -50,15 +50,18 @@
     }
 
     override fun expectedDistanceTo(index: Int, targetScrollOffset: Int): Float {
-        val visibleItems = state.layoutInfo.visibleItemsInfo
-        val itemSizeSum = visibleItems
-            .fastSumBy { if (state.isVertical) it.size.height else it.size.width }
-        val averageMainAxisItemSize = itemSizeSum / (visibleItems.size * state.laneCount)
+        val layoutInfo = state.layoutInfo
+        val visibleItems = layoutInfo.visibleItemsInfo
+        val itemSizeSum = visibleItems.fastSumBy {
+            if (state.isVertical) it.size.height else it.size.width
+        }
+        val averageMainAxisItemSize =
+            itemSizeSum / visibleItems.size + layoutInfo.mainAxisItemSpacing
 
-        val indexesDiff = index - firstVisibleItemIndex
+        val lineDiff = index / state.laneCount - firstVisibleItemIndex / state.laneCount
         var coercedOffset = minOf(abs(targetScrollOffset), averageMainAxisItemSize)
         if (targetScrollOffset < 0) coercedOffset *= -1
-        return (averageMainAxisItemSize * indexesDiff).toFloat() +
+        return averageMainAxisItemSize * lineDiff.toFloat() +
             coercedOffset - firstVisibleItemScrollOffset
     }
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridDsl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridDsl.kt
index 8941796..cca7a11 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridDsl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridDsl.kt
@@ -241,11 +241,6 @@
 internal annotation class LazyStaggeredGridScopeMarker
 
 /**
- * Receiver scope for itemContent in [LazyStaggeredGridScope.item]
- */
-sealed interface LazyStaggeredGridItemScope
-
-/**
  * Receiver scope for [LazyVerticalStaggeredGrid] and [LazyHorizontalStaggeredGrid]
  */
 @LazyStaggeredGridScopeMarker
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridIntervalContent.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridIntervalContent.kt
index 4db8415..dc7406d 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridIntervalContent.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridIntervalContent.kt
@@ -69,9 +69,6 @@
 }
 
 @OptIn(ExperimentalFoundationApi::class)
-internal object LazyStaggeredGridItemScopeImpl : LazyStaggeredGridItemScope
-
-@OptIn(ExperimentalFoundationApi::class)
 internal class LazyStaggeredGridInterval(
     override val key: ((index: Int) -> Any)?,
     override val type: ((index: Int) -> Any?),
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemPlacementAnimator.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemPlacementAnimator.kt
new file mode 100644
index 0000000..11895ed
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemPlacementAnimator.kt
@@ -0,0 +1,280 @@
+/*
+ * 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.compose.foundation.lazy.staggeredgrid
+
+import androidx.compose.foundation.lazy.layout.LazyLayoutAnimateItemModifierNode
+import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.util.fastAny
+import androidx.compose.ui.util.fastForEach
+
+/**
+ * Handles the item placement animations when it is set via
+ * [LazyStaggeredGridItemScope.animateItemPlacement].
+ *
+ * This class is responsible for detecting when item position changed, figuring our start/end
+ * offsets and starting the animations.
+ */
+internal class LazyStaggeredGridItemPlacementAnimator {
+    // state containing relevant info for active items.
+    private val keyToItemInfoMap = mutableMapOf<Any, ItemInfo>()
+
+    // snapshot of the key to index map used for the last measuring.
+    private var keyToIndexMap: LazyLayoutKeyIndexMap = LazyLayoutKeyIndexMap
+
+    // keeps the index of the first visible item index.
+    private var firstVisibleIndex = 0
+
+    // stored to not allocate it every pass.
+    private val movingAwayKeys = LinkedHashSet<Any>()
+    private val movingInFromStartBound = mutableListOf<LazyStaggeredGridPositionedItem>()
+    private val movingInFromEndBound = mutableListOf<LazyStaggeredGridPositionedItem>()
+    private val movingAwayToStartBound = mutableListOf<LazyStaggeredGridMeasuredItem>()
+    private val movingAwayToEndBound = mutableListOf<LazyStaggeredGridMeasuredItem>()
+
+    /**
+     * Should be called after the measuring so we can detect position changes and start animations.
+     *
+     * Note that this method can compose new item and add it into the [positionedItems] list.
+     */
+    fun onMeasured(
+        consumedScroll: Int,
+        layoutWidth: Int,
+        layoutHeight: Int,
+        positionedItems: MutableList<LazyStaggeredGridPositionedItem>,
+        itemProvider: LazyStaggeredGridMeasureProvider,
+        isVertical: Boolean,
+        laneCount: Int
+    ) {
+        if (!positionedItems.fastAny { it.hasAnimations } && keyToItemInfoMap.isEmpty()) {
+            // no animations specified - no work needed
+            reset()
+            return
+        }
+
+        val previousFirstVisibleIndex = firstVisibleIndex
+        firstVisibleIndex = positionedItems.firstOrNull()?.index ?: 0
+        val previousKeyToIndexMap = keyToIndexMap
+        keyToIndexMap = itemProvider.keyToIndexMap
+
+        val mainAxisLayoutSize = if (isVertical) layoutHeight else layoutWidth
+
+        // the consumed scroll is considered as a delta we don't need to animate
+        val scrollOffset = if (isVertical) {
+            IntOffset(0, consumedScroll)
+        } else {
+            IntOffset(consumedScroll, 0)
+        }
+
+        // first add all items we had in the previous run
+        movingAwayKeys.addAll(keyToItemInfoMap.keys)
+        // iterate through the items which are visible (without animated offsets)
+        positionedItems.fastForEach { item ->
+            // remove items we have in the current one as they are still visible.
+            movingAwayKeys.remove(item.key)
+            if (item.hasAnimations) {
+                val itemInfo = keyToItemInfoMap[item.key]
+                // there is no state associated with this item yet
+                if (itemInfo == null) {
+                    keyToItemInfoMap[item.key] =
+                        ItemInfo(item.lane, item.span, item.crossAxisOffset)
+                    val previousIndex = previousKeyToIndexMap[item.key]
+                    if (previousIndex != -1 && item.index != previousIndex) {
+                        if (previousIndex < previousFirstVisibleIndex) {
+                            // the larger index will be in the start of the list
+                            movingInFromStartBound.add(item)
+                        } else {
+                            movingInFromEndBound.add(item)
+                        }
+                    } else {
+                        initializeNode(
+                            item,
+                            item.offset.let { if (item.isVertical) it.y else it.x }
+                        )
+                    }
+                } else {
+                    item.forEachNode {
+                        if (it.rawOffset != LazyLayoutAnimateItemModifierNode.NotInitialized) {
+                            it.rawOffset += scrollOffset
+                        }
+                    }
+                    itemInfo.lane = item.lane
+                    itemInfo.span = item.span
+                    itemInfo.crossAxisOffset = item.crossAxisOffset
+                    startAnimationsIfNeeded(item)
+                }
+            } else {
+                // no animation, clean up if needed
+                keyToItemInfoMap.remove(item.key)
+            }
+        }
+
+        val accumulatedOffsetPerLane = IntArray(laneCount) { 0 }
+        if (movingInFromStartBound.isNotEmpty()) {
+            movingInFromStartBound.sortByDescending { previousKeyToIndexMap[it.key] }
+            movingInFromStartBound.fastForEach { item ->
+                accumulatedOffsetPerLane[item.lane] += item.mainAxisSize
+                val mainAxisOffset = 0 - accumulatedOffsetPerLane[item.lane]
+                initializeNode(item, mainAxisOffset)
+                startAnimationsIfNeeded(item)
+            }
+            accumulatedOffsetPerLane.fill(0)
+        }
+        if (movingInFromEndBound.isNotEmpty()) {
+            movingInFromEndBound.sortBy { previousKeyToIndexMap[it.key] }
+            movingInFromEndBound.fastForEach { item ->
+                val mainAxisOffset = mainAxisLayoutSize + accumulatedOffsetPerLane[item.lane]
+                accumulatedOffsetPerLane[item.lane] += item.mainAxisSize
+                initializeNode(item, mainAxisOffset)
+                startAnimationsIfNeeded(item)
+            }
+            accumulatedOffsetPerLane.fill(0)
+        }
+
+        movingAwayKeys.forEach { key ->
+            // found an item which was in our map previously but is not a part of the
+            // positionedItems now
+            val itemInfo = keyToItemInfoMap.getValue(key)
+            val newIndex = keyToIndexMap[key]
+
+            if (newIndex == -1) {
+                keyToItemInfoMap.remove(key)
+            } else {
+                val item = itemProvider.getAndMeasure(
+                    newIndex,
+                    SpanRange(itemInfo.lane, itemInfo.span)
+                )
+                // check if we have any active placement animation on the item
+                var inProgress = false
+                repeat(item.placeablesCount) {
+                    if (item.getParentData(it).node?.isAnimationInProgress == true) {
+                        inProgress = true
+                        return@repeat
+                    }
+                }
+                if ((!inProgress && newIndex == previousKeyToIndexMap[key])) {
+                    keyToItemInfoMap.remove(key)
+                } else {
+                    if (newIndex < firstVisibleIndex) {
+                        movingAwayToStartBound.add(item)
+                    } else {
+                        movingAwayToEndBound.add(item)
+                    }
+                }
+            }
+        }
+
+        if (movingAwayToStartBound.isNotEmpty()) {
+            movingAwayToStartBound.sortByDescending { keyToIndexMap[it.key] }
+            movingAwayToStartBound.fastForEach { item ->
+                accumulatedOffsetPerLane[item.lane] += item.mainAxisSize
+                val mainAxisOffset = 0 - accumulatedOffsetPerLane[item.lane]
+
+                val itemInfo = keyToItemInfoMap.getValue(item.key)
+                val positionedItem =
+                    item.position(mainAxisOffset, itemInfo.crossAxisOffset, mainAxisLayoutSize)
+                positionedItems.add(positionedItem)
+                startAnimationsIfNeeded(positionedItem)
+            }
+            accumulatedOffsetPerLane.fill(0)
+        }
+        if (movingAwayToEndBound.isNotEmpty()) {
+            movingAwayToEndBound.sortBy { keyToIndexMap[it.key] }
+            movingAwayToEndBound.fastForEach { item ->
+                val mainAxisOffset = mainAxisLayoutSize + accumulatedOffsetPerLane[item.lane]
+                accumulatedOffsetPerLane[item.lane] += item.mainAxisSize
+
+                val itemInfo = keyToItemInfoMap.getValue(item.key)
+                val positionedItem =
+                    item.position(mainAxisOffset, itemInfo.crossAxisOffset, mainAxisLayoutSize)
+                positionedItems.add(positionedItem)
+                startAnimationsIfNeeded(positionedItem)
+            }
+        }
+
+        movingInFromStartBound.clear()
+        movingInFromEndBound.clear()
+        movingAwayToStartBound.clear()
+        movingAwayToEndBound.clear()
+        movingAwayKeys.clear()
+    }
+
+    /**
+     * Should be called when the animations are not needed for the next positions change,
+     * for example when we snap to a new position.
+     */
+    fun reset() {
+        keyToItemInfoMap.clear()
+        keyToIndexMap = LazyLayoutKeyIndexMap
+        firstVisibleIndex = -1
+    }
+
+    private fun initializeNode(
+        item: LazyStaggeredGridPositionedItem,
+        mainAxisOffset: Int
+    ) {
+        val firstPlaceableOffset = item.offset
+
+        val targetFirstPlaceableOffset = if (item.isVertical) {
+            firstPlaceableOffset.copy(y = mainAxisOffset)
+        } else {
+            firstPlaceableOffset.copy(x = mainAxisOffset)
+        }
+
+        // initialize offsets
+        item.forEachNode { node ->
+            val diffToFirstPlaceableOffset =
+                item.offset - firstPlaceableOffset
+            node.rawOffset = targetFirstPlaceableOffset + diffToFirstPlaceableOffset
+        }
+    }
+
+    private fun startAnimationsIfNeeded(item: LazyStaggeredGridPositionedItem) {
+        item.forEachNode { node ->
+            val newTarget = item.offset
+            val currentTarget = node.rawOffset
+            if (currentTarget != LazyLayoutAnimateItemModifierNode.NotInitialized &&
+                currentTarget != newTarget
+            ) {
+                node.animatePlacementDelta(newTarget - currentTarget)
+            }
+            node.rawOffset = newTarget
+        }
+    }
+
+    private val Any?.node get() = this as? LazyLayoutAnimateItemModifierNode
+
+    private val LazyStaggeredGridPositionedItem.hasAnimations: Boolean
+        get() {
+            forEachNode { return true }
+            return false
+        }
+
+    private inline fun LazyStaggeredGridPositionedItem.forEachNode(
+        block: (LazyLayoutAnimateItemModifierNode) -> Unit
+    ) {
+        repeat(placeablesCount) { index ->
+            getParentData(index).node?.let(block)
+        }
+    }
+}
+
+private class ItemInfo(
+    var lane: Int,
+    var span: Int,
+    var crossAxisOffset: Int
+)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt
index f9a8f36..b54bd72 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt
@@ -31,6 +31,7 @@
 @OptIn(ExperimentalFoundationApi::class)
 internal interface LazyStaggeredGridItemProvider : LazyLayoutItemProvider {
     val spanProvider: LazyStaggeredGridSpanProvider
+    val keyToIndexMap: LazyLayoutKeyIndexMap
 }
 
 @Composable
@@ -56,7 +57,7 @@
         LazyStaggeredGridIntervalContent(latestContent())
     }
 
-    private val keyToIndexMap: LazyLayoutKeyIndexMap by NearestRangeKeyIndexMapState(
+    override val keyToIndexMap: LazyLayoutKeyIndexMap by NearestRangeKeyIndexMapState(
         firstVisibleItemIndex = { state.firstVisibleItemIndex },
         slidingWindowSize = { 90 },
         extraItemCount = { 200 },
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemScope.kt
new file mode 100644
index 0000000..5982746
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemScope.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2022 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.compose.foundation.lazy.staggeredgrid
+
+import androidx.compose.animation.core.FiniteAnimationSpec
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.VisibilityThreshold
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.lazy.layout.LazyLayoutAnimateItemModifierNode
+import androidx.compose.runtime.Stable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.node.DelegatingNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.ParentDataModifierNode
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntOffset
+
+/**
+ * Receiver scope for itemContent in [LazyStaggeredGridScope.item]
+ */
+@Stable
+@LazyStaggeredGridScopeMarker
+sealed interface LazyStaggeredGridItemScope {
+    /**
+     * This modifier animates the item placement within the grid.
+     *
+     * When you scroll backward staggered grids could move already visible items in order
+     * to correct the accumulated errors in previous item size estimations. This modifier
+     * can animate such moves.
+     *
+     * Aside from that when you provide a key via [LazyStaggeredGridScope.item] /
+     * [LazyStaggeredGridScope.items] this modifier will enable item reordering animations.
+     *
+     * @param animationSpec a finite animation that will be used to animate the item placement.
+     */
+    @ExperimentalFoundationApi
+    fun Modifier.animateItemPlacement(
+        animationSpec: FiniteAnimationSpec<IntOffset> = spring(
+            stiffness = Spring.StiffnessMediumLow,
+            visibilityThreshold = IntOffset.VisibilityThreshold
+        )
+    ): Modifier
+}
+
+@OptIn(ExperimentalFoundationApi::class)
+internal object LazyStaggeredGridItemScopeImpl : LazyStaggeredGridItemScope {
+    @ExperimentalFoundationApi
+    override fun Modifier.animateItemPlacement(animationSpec: FiniteAnimationSpec<IntOffset>) =
+        this then AnimateItemPlacementElement(animationSpec)
+}
+
+private class AnimateItemPlacementElement(
+    val animationSpec: FiniteAnimationSpec<IntOffset>
+) : ModifierNodeElement<AnimateItemPlacementNode>() {
+
+    override fun create(): AnimateItemPlacementNode = AnimateItemPlacementNode(animationSpec)
+
+    override fun update(node: AnimateItemPlacementNode) {
+        node.delegatingNode.placementAnimationSpec = animationSpec
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is AnimateItemPlacementElement) return false
+        return animationSpec != other.animationSpec
+    }
+
+    override fun hashCode(): Int {
+        return animationSpec.hashCode()
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "animateItemPlacement"
+        value = animationSpec
+    }
+}
+
+private class AnimateItemPlacementNode(
+    animationSpec: FiniteAnimationSpec<IntOffset>
+) : DelegatingNode(), ParentDataModifierNode {
+
+    val delegatingNode = delegate(LazyLayoutAnimateItemModifierNode(animationSpec))
+
+    override fun Density.modifyParentData(parentData: Any?): Any = delegatingNode
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt
index 990b5ad..b653fd7 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt
@@ -18,7 +18,8 @@
 
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.fastMaxOfOrNull
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
+import androidx.compose.foundation.lazy.layout.LazyLayoutAnimateItemModifierNode
+import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope
 import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridLaneInfo.Companion.FullSpan
 import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridLaneInfo.Companion.Unset
@@ -30,6 +31,7 @@
 import androidx.compose.ui.unit.constrainHeight
 import androidx.compose.ui.unit.constrainWidth
 import androidx.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastForEachIndexed
 import androidx.compose.ui.util.packInts
 import androidx.compose.ui.util.unpackInt1
 import androidx.compose.ui.util.unpackInt2
@@ -164,7 +166,7 @@
 }
 
 @OptIn(ExperimentalFoundationApi::class)
-private class LazyStaggeredGridMeasureContext(
+internal class LazyStaggeredGridMeasureContext(
     val state: LazyStaggeredGridState,
     val pinnedItems: List<Int>,
     val itemProvider: LazyStaggeredGridItemProvider,
@@ -193,6 +195,8 @@
             spacing = mainAxisSpacing,
             lane = lane,
             span = span,
+            beforeContentPadding = beforeContentPadding,
+            afterContentPadding = afterContentPadding
         )
     }
 
@@ -664,7 +668,7 @@
         // even if we compose items to fill before content padding we should ignore items fully
         // located there for the state's scroll position calculation (first item + first offset)
         debugLog { "adjusting for content padding" }
-        if (beforeContentPadding > 0) {
+        if (beforeContentPadding > mainAxisSpacing) {
             for (laneIndex in measuredItems.indices) {
                 val laneItems = measuredItems[laneIndex]
                 for (i in laneItems.indices) {
@@ -676,7 +680,6 @@
                         firstItemOffsets[laneIndex] != 0 &&
                         firstItemOffsets[laneIndex] >= size
                     ) {
-
                         firstItemOffsets[laneIndex] -= size
                         firstItemIndices[laneIndex] = laneItems[i + 1].index
                     } else {
@@ -708,13 +711,22 @@
         }
 
         val mainAxisLayoutSize =
-            min(if (isVertical) layoutHeight else layoutWidth, mainAxisAvailableSize)
+            min(if (isVertical) layoutHeight else layoutWidth, mainAxisAvailableSize).let {
+                // The offsets are calculated in [-beforePad; size + afterPad] interval
+                // Ensure the layout size used for positioning (and reverse layout calculation)
+                // is in the same interval.
+                it - beforeContentPadding + afterContentPadding
+            }
 
         var extraItemOffset = itemScrollOffsets[0]
         val extraItemsBefore = calculateExtraItems(
             position = {
                 extraItemOffset -= it.sizeWithSpacings
-                it.position(0, extraItemOffset, 0, mainAxisLayoutSize)
+                it.position(
+                    mainAxis = extraItemOffset,
+                    crossAxis = 0,
+                    mainAxisLayoutSize = mainAxisLayoutSize
+                )
             },
             filter = { itemIndex ->
                 val lane = laneInfo.getLane(itemIndex)
@@ -729,7 +741,7 @@
             }
         )
 
-        val positionedItems = calculatePositionedItems(
+        val visibleItems = calculateVisibleItems(
             measuredItems,
             itemScrollOffsets,
             mainAxisLayoutSize,
@@ -738,7 +750,11 @@
         extraItemOffset = itemScrollOffsets[0]
         val extraItemsAfter = calculateExtraItems(
             position = {
-                val positionedItem = it.position(0, extraItemOffset, 0, mainAxisLayoutSize)
+                val positionedItem = it.position(
+                    mainAxis = extraItemOffset,
+                    crossAxis = 0,
+                    mainAxisLayoutSize = mainAxisLayoutSize
+                )
                 extraItemOffset += it.sizeWithSpacings
                 positionedItem
             },
@@ -758,10 +774,25 @@
             }
         )
 
+        val positionedItems = mutableListOf<LazyStaggeredGridPositionedItem>()
+        positionedItems.addAll(extraItemsBefore)
+        positionedItems.addAll(visibleItems)
+        positionedItems.addAll(extraItemsAfter)
+
         debugLog {
             "positioned: $positionedItems"
         }
 
+        state.placementAnimator.onMeasured(
+            consumedScroll = consumedScroll.toInt(),
+            layoutWidth = layoutWidth,
+            layoutHeight = layoutHeight,
+            positionedItems = positionedItems,
+            itemProvider = measuredItemProvider,
+            isVertical = isVertical,
+            laneCount = laneCount
+        )
+
         // end placement
 
         // only scroll backward if the first item is not on screen or fully visible
@@ -775,22 +806,14 @@
             firstVisibleItemScrollOffsets = firstItemOffsets,
             consumedScroll = consumedScroll,
             measureResult = layout(layoutWidth, layoutHeight) {
-                extraItemsBefore.fastForEach { item ->
-                    item.place(scope = this, context = this@measure)
-                }
-
                 positionedItems.fastForEach { item ->
                     item.place(scope = this, context = this@measure)
                 }
-
-                extraItemsAfter.fastForEach { item ->
-                    item.place(scope = this, context = this@measure)
-                }
             },
             canScrollForward = canScrollForward,
             canScrollBackward = canScrollBackward,
             isVertical = isVertical,
-            visibleItemsInfo = positionedItems,
+            visibleItemsInfo = visibleItems,
             totalItemsCount = itemCount,
             viewportSize = IntSize(layoutWidth, layoutHeight),
             viewportStartOffset = minOffset,
@@ -802,7 +825,7 @@
     }
 }
 
-private fun LazyStaggeredGridMeasureContext.calculatePositionedItems(
+private fun LazyStaggeredGridMeasureContext.calculateVisibleItems(
     measuredItems: Array<ArrayDeque<LazyStaggeredGridMeasuredItem>>,
     itemScrollOffsets: IntArray,
     mainAxisLayoutSize: Int,
@@ -825,13 +848,18 @@
         val mainAxisOffset = itemScrollOffsets.maxInRange(spanRange)
         val crossAxisOffset = resolvedSlots.positions[laneIndex]
 
-        if (item.placeables.isEmpty()) {
+        if (item.placeablesCount == 0) {
             // nothing to place, ignore spacings
             continue
         }
 
         positionedItems +=
-            item.position(laneIndex, mainAxisOffset, crossAxisOffset, mainAxisLayoutSize)
+            item.position(
+                mainAxis = mainAxisOffset,
+                crossAxis = crossAxisOffset,
+                mainAxisLayoutSize = mainAxisLayoutSize,
+                lane = laneIndex
+            )
         spanRange.forEach { lane ->
             itemScrollOffsets[lane] = mainAxisOffset + item.sizeWithSpacings
         }
@@ -861,7 +889,7 @@
 }
 
 @JvmInline
-private value class SpanRange private constructor(val packedValue: Long) {
+internal value class SpanRange private constructor(val packedValue: Long) {
     constructor(lane: Int, span: Int) : this(packInts(lane, lane + span))
 
     inline val start get(): Int = unpackInt1(packedValue)
@@ -958,9 +986,9 @@
     laneInfo.findPreviousItemIndex(item, lane)
 
 @OptIn(ExperimentalFoundationApi::class)
-private class LazyStaggeredGridMeasureProvider(
+internal class LazyStaggeredGridMeasureProvider(
     private val isVertical: Boolean,
-    private val itemProvider: LazyLayoutItemProvider,
+    private val itemProvider: LazyStaggeredGridItemProvider,
     private val measureScope: LazyLayoutMeasureScope,
     private val resolvedSlots: LazyStaggeredGridSlots,
     private val measuredItemFactory: MeasuredItemFactory,
@@ -988,10 +1016,12 @@
         val placeables = measureScope.measure(index, childConstraints(span.start, span.size))
         return measuredItemFactory.createItem(index, span.start, span.size, key, placeables)
     }
+
+    val keyToIndexMap: LazyLayoutKeyIndexMap get() = itemProvider.keyToIndexMap
 }
 
 // This interface allows to avoid autoboxing on index param
-private fun interface MeasuredItemFactory {
+internal fun interface MeasuredItemFactory {
     fun createItem(
         index: Int,
         lane: Int,
@@ -1001,17 +1031,23 @@
     ): LazyStaggeredGridMeasuredItem
 }
 
-private class LazyStaggeredGridMeasuredItem(
+internal class LazyStaggeredGridMeasuredItem(
     val index: Int,
     val key: Any,
-    val placeables: List<Placeable>,
-    val isVertical: Boolean,
-    val spacing: Int,
+    private val placeables: List<Placeable>,
+    private val isVertical: Boolean,
+    spacing: Int,
     val lane: Int,
     val span: Int,
+    private val beforeContentPadding: Int,
+    private val afterContentPadding: Int,
 ) {
     var isVisible = true
 
+    val placeablesCount: Int get() = placeables.size
+
+    fun getParentData(index: Int) = placeables[index].parentData
+
     val mainAxisSize: Int = placeables.fastMaxOfOrNull { placeable ->
         if (isVertical) placeable.height else placeable.width
     } ?: 0
@@ -1023,10 +1059,10 @@
     } ?: 0
 
     fun position(
-        lane: Int,
         mainAxis: Int,
         crossAxis: Int,
         mainAxisLayoutSize: Int,
+        lane: Int = 0
     ): LazyStaggeredGridPositionedItem =
         LazyStaggeredGridPositionedItem(
             offset = if (isVertical) {
@@ -1038,46 +1074,74 @@
             index = index,
             key = key,
             size = if (isVertical) {
-                IntSize(crossAxisSize, sizeWithSpacings)
+                IntSize(crossAxisSize, mainAxisSize)
             } else {
-                IntSize(sizeWithSpacings, crossAxisSize)
+                IntSize(mainAxisSize, crossAxisSize)
             },
             placeables = placeables,
             isVertical = isVertical,
             mainAxisLayoutSize = mainAxisLayoutSize,
+            minMainAxisOffset = -beforeContentPadding,
+            maxMainAxisOffset = mainAxisLayoutSize + afterContentPadding,
+            span = span
         )
 }
 
-@OptIn(ExperimentalFoundationApi::class)
-private class LazyStaggeredGridPositionedItem(
+internal class LazyStaggeredGridPositionedItem(
     override val offset: IntOffset,
     override val index: Int,
     override val lane: Int,
     override val key: Any,
     override val size: IntSize,
     private val placeables: List<Placeable>,
-    private val isVertical: Boolean,
+    val isVertical: Boolean,
     private val mainAxisLayoutSize: Int,
+    private val minMainAxisOffset: Int,
+    private val maxMainAxisOffset: Int,
+    val span: Int
 ) : LazyStaggeredGridItemInfo {
+
+    val placeablesCount: Int get() = placeables.size
+
+    val mainAxisSize get() = if (isVertical) size.height else size.width
+
+    val crossAxisOffset get() = if (isVertical) offset.x else offset.y
+
+    fun getParentData(index: Int) = placeables[index].parentData
+
     fun place(
         scope: Placeable.PlacementScope,
         context: LazyStaggeredGridMeasureContext
     ) = with(context) {
         with(scope) {
-            placeables.fastForEach { placeable ->
-                val reverseLayoutAwareOffset = if (reverseLayout) {
-                    offset.copy { mainAxisOffset ->
+            placeables.fastForEachIndexed { index, placeable ->
+                val minOffset = minMainAxisOffset - placeable.mainAxisSize
+                val maxOffset = maxMainAxisOffset
+
+                var offset = offset
+                val animateNode = getParentData(index) as? LazyLayoutAnimateItemModifierNode
+                if (animateNode != null) {
+                    val animatedOffset = offset + animateNode.placementDelta
+                    // cancel the animation if current and target offsets are both out of the bounds.
+                    if ((offset.mainAxis <= minOffset && animatedOffset.mainAxis <= minOffset) ||
+                        (offset.mainAxis >= maxOffset && animatedOffset.mainAxis >= maxOffset)
+                    ) {
+                        animateNode.cancelAnimation()
+                    }
+                    offset = animatedOffset
+                }
+                if (reverseLayout) {
+                    offset = offset.copy { mainAxisOffset ->
                         mainAxisLayoutSize - mainAxisOffset - placeable.mainAxisSize
                     }
-                } else {
-                    offset
                 }
-
-                placeable.placeRelativeWithLayer(reverseLayoutAwareOffset + contentOffset)
+                offset += contentOffset
+                placeable.placeRelativeWithLayer(offset)
             }
         }
     }
 
+    private val IntOffset.mainAxis get() = if (isVertical) y else x
     private inline val Placeable.mainAxisSize get() = if (isVertical) height else width
     private inline fun IntOffset.copy(mainAxisMap: (Int) -> Int): IntOffset =
         IntOffset(if (isVertical) x else mainAxisMap(x), if (isVertical) mainAxisMap(y) else y)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt
index 54c5e9e..a1b62d6 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt
@@ -214,6 +214,8 @@
      */
     internal val pinnedItems = LazyLayoutPinnedItemList()
 
+    internal val placementAnimator = LazyStaggeredGridItemPlacementAnimator()
+
     /**
      * Call this function to take control of scrolling and gain the ability to send scroll events
      * via [ScrollScope.scrollBy]. All actions that change the logical scroll position must be
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewRequester.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewRequester.kt
index b0c7eaf..2288769 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewRequester.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewRequester.kt
@@ -120,10 +120,9 @@
         return BringIntoViewRequesterNode(requester)
     }
 
-    override fun update(node: BringIntoViewRequesterNode): BringIntoViewRequesterNode =
-        node.also {
-            it.updateRequester(requester)
-        }
+    override fun update(node: BringIntoViewRequesterNode) {
+        node.updateRequester(requester)
+    }
 
     override fun InspectorInfo.inspectableProperties() {
         name = "bringIntoViewRequester"
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.kt
index 9e31be2..1c91070 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.kt
@@ -106,8 +106,8 @@
 ) : ModifierNodeElement<BringIntoViewResponderNode>() {
     override fun create(): BringIntoViewResponderNode = BringIntoViewResponderNode(responder)
 
-    override fun update(node: BringIntoViewResponderNode) = node.also {
-        it.responder = responder
+    override fun update(node: BringIntoViewResponderNode) {
+        node.responder = responder
     }
     override fun equals(other: Any?): Boolean {
         return (this === other) ||
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt
index b2293d4..4d22aeb 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt
@@ -60,7 +60,7 @@
 
     override fun update(
         node: SelectableTextAnnotatedStringNode
-    ): SelectableTextAnnotatedStringNode {
+    ) {
         node.update(
             text = text,
             style = style,
@@ -74,7 +74,6 @@
             onPlaceholderLayout = onPlaceholderLayout,
             selectionController = selectionController
         )
-        return node
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt
index 245b485..cac5e39 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt
@@ -30,7 +30,7 @@
 import androidx.compose.ui.node.GlobalPositionAwareModifierNode
 import androidx.compose.ui.node.LayoutModifierNode
 import androidx.compose.ui.node.SemanticsModifierNode
-import androidx.compose.ui.node.invalidateMeasurements
+import androidx.compose.ui.node.invalidateMeasurement
 import androidx.compose.ui.semantics.SemanticsConfiguration
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.Placeholder
@@ -149,6 +149,6 @@
             )
         )
         // we always relayout when we're selectable
-        invalidateMeasurements()
+        invalidateMeasurement()
     }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt
index 377e096..6232e52 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt
@@ -60,7 +60,7 @@
         selectionController
     )
 
-    override fun update(node: TextAnnotatedStringNode): TextAnnotatedStringNode {
+    override fun update(node: TextAnnotatedStringNode) {
         node.doInvalidations(
             textChanged = node.updateText(
                 text = text
@@ -80,7 +80,6 @@
                 selectionController = selectionController
             )
         )
-        return node
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
index f948a2f..7d4e8d4 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
@@ -34,7 +34,7 @@
 import androidx.compose.ui.node.SemanticsModifierNode
 import androidx.compose.ui.node.invalidateDraw
 import androidx.compose.ui.node.invalidateLayer
-import androidx.compose.ui.node.invalidateMeasurements
+import androidx.compose.ui.node.invalidateMeasurement
 import androidx.compose.ui.node.invalidateSemantics
 import androidx.compose.ui.semantics.SemanticsConfiguration
 import androidx.compose.ui.semantics.getTextLayoutResult
@@ -200,7 +200,7 @@
                 minLines = minLines,
                 placeholders = placeholders
             )
-            invalidateMeasurements()
+            invalidateMeasurement()
             invalidateDraw()
         }
     }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt
index 63be1b7..bb846b3 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt
@@ -49,7 +49,7 @@
         minLines
     )
 
-    override fun update(node: TextStringSimpleNode): TextStringSimpleNode {
+    override fun update(node: TextStringSimpleNode) {
         node.doInvalidations(
             textChanged = node.updateText(
                 text = text
@@ -63,7 +63,6 @@
                 overflow = overflow
             )
         )
-        return node
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt
index 93c1391..ca2ea56 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt
@@ -37,7 +37,7 @@
 import androidx.compose.ui.node.LayoutModifierNode
 import androidx.compose.ui.node.SemanticsModifierNode
 import androidx.compose.ui.node.invalidateLayer
-import androidx.compose.ui.node.invalidateMeasurements
+import androidx.compose.ui.node.invalidateMeasurement
 import androidx.compose.ui.node.invalidateSemantics
 import androidx.compose.ui.semantics.SemanticsConfiguration
 import androidx.compose.ui.semantics.getTextLayoutResult
@@ -168,7 +168,7 @@
                 maxLines = maxLines,
                 minLines = minLines
             )
-            invalidateMeasurements()
+            invalidateMeasurement()
             invalidateLayer()
         }
     }
diff --git a/compose/material/material-icons-extended/build.gradle b/compose/material/material-icons-extended/build.gradle
index 4a58d27..0903147 100644
--- a/compose/material/material-icons-extended/build.gradle
+++ b/compose/material/material-icons-extended/build.gradle
@@ -86,8 +86,6 @@
     }
 }
 
-def allThemes = ["filled", "outlined", "rounded", "sharp", "twotone"]
-
 configurations {
     embedThemesDebug {
         attributes {
@@ -105,10 +103,17 @@
 }
 
 if (!AndroidXComposePlugin.isMultiplatformEnabled(project)) {
-    for (themeName in allThemes) {
-        def otherProject = project(":compose:material:material-icons-extended-" + themeName)
-        project.dependencies.add("embedThemesDebug", otherProject)
-        project.dependencies.add("embedThemesRelease", otherProject)
+    def allThemeProjects = [
+            project(":compose:material:material-icons-extended-filled"),
+            project(":compose:material:material-icons-extended-outlined"),
+            project(":compose:material:material-icons-extended-rounded"),
+            project(":compose:material:material-icons-extended-sharp"),
+            project(":compose:material:material-icons-extended-twotone")
+    ]
+
+    for (themeProject in allThemeProjects) {
+        project.dependencies.add("embedThemesDebug", themeProject)
+        project.dependencies.add("embedThemesRelease", themeProject)
     }
     // Compiling all of the icons in this project takes a while,
     // so when possible, we compile each theme in its own project and merge them here.
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index 0a71de1..d9fe905 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -777,7 +777,7 @@
     method public final androidx.compose.runtime.State<java.lang.Float> getOffset();
     method public final androidx.compose.runtime.State<java.lang.Float> getOverflow();
     method public final androidx.compose.material.SwipeProgress<T> getProgress();
-    method public final T! getTargetValue();
+    method public final T getTargetValue();
     method public final boolean isAnimationRunning();
     method public final float performDrag(float delta);
     method public final suspend Object? performFling(float velocity, kotlin.coroutines.Continuation<? super kotlin.Unit>);
@@ -788,7 +788,7 @@
     property public final androidx.compose.runtime.State<java.lang.Float> offset;
     property public final androidx.compose.runtime.State<java.lang.Float> overflow;
     property @androidx.compose.material.ExperimentalMaterialApi public final androidx.compose.material.SwipeProgress<T> progress;
-    property @androidx.compose.material.ExperimentalMaterialApi public final T! targetValue;
+    property @androidx.compose.material.ExperimentalMaterialApi public final T targetValue;
     field public static final androidx.compose.material.SwipeableState.Companion Companion;
   }
 
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt
index 257e39c..dbd9be9 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt
@@ -52,16 +52,15 @@
 import androidx.compose.ui.unit.Velocity
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.lerp
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.take
-import kotlinx.coroutines.launch
 import kotlin.math.PI
 import kotlin.math.abs
 import kotlin.math.sign
 import kotlin.math.sin
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.launch
 
 /**
  * State of the [swipeable] modifier.
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TabRow.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TabRow.kt
index 92c174f..78112ad2 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TabRow.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TabRow.kt
@@ -25,8 +25,8 @@
 import androidx.compose.foundation.horizontalScroll
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.foundation.rememberScrollState
@@ -133,10 +133,10 @@
     contentColor: Color = contentColorFor(backgroundColor),
     indicator: @Composable @UiComposable
         (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->
-            TabRowDefaults.Indicator(
-                Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
-            )
-        },
+        TabRowDefaults.Indicator(
+            Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
+        )
+    },
     divider: @Composable @UiComposable () -> Unit =
         @Composable {
             TabRowDefaults.Divider()
@@ -228,10 +228,10 @@
     edgePadding: Dp = TabRowDefaults.ScrollableTabRowPadding,
     indicator: @Composable @UiComposable
         (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->
-            TabRowDefaults.Indicator(
-                Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
-            )
-        },
+        TabRowDefaults.Indicator(
+            Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
+        )
+    },
     divider: @Composable @UiComposable () -> Unit =
         @Composable {
             TabRowDefaults.Divider()
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 0901450..d2b53fb 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -818,7 +818,7 @@
 
   public final class TextKt {
     method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index d920d2a..c580cf9 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -1204,7 +1204,7 @@
 
   public final class TextKt {
     method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 0901450..d2b53fb 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -818,7 +818,7 @@
 
   public final class TextKt {
     method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
     method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
diff --git a/compose/material3/material3/build.gradle b/compose/material3/material3/build.gradle
index 10979b6..6fe5660 100644
--- a/compose/material3/material3/build.gradle
+++ b/compose/material3/material3/build.gradle
@@ -38,9 +38,9 @@
         implementation(libs.kotlinStdlibCommon)
         implementation("androidx.activity:activity-compose:1.5.0")
         implementation("androidx.compose.animation:animation-core:1.4.2")
-        implementation("androidx.compose.foundation:foundation-layout:1.4.2")
+        implementation(project(":compose:foundation:foundation-layout"))
         implementation("androidx.compose.ui:ui-util:1.4.2")
-        api("androidx.compose.foundation:foundation:1.4.2")
+        api(project(":compose:foundation:foundation"))
         api("androidx.compose.material:material-icons-core:1.4.2")
         api("androidx.compose.material:material-ripple:1.4.2")
         api("androidx.compose.runtime:runtime:1.4.2")
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
index 9f0f5e4..2e60a0a 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
@@ -17,6 +17,7 @@
 package androidx.compose.material3
 
 import android.os.Build
+import android.os.Build.VERSION.SDK_INT
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.runtime.Composable
@@ -32,6 +33,8 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Assume
+import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -47,6 +50,13 @@
     @get:Rule
     val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL3)
 
+    @Before
+    fun before() {
+        // Disable tests for API 33 until a solution can be found
+        // to make these tests stable for Firebase API 33 tests.
+        Assume.assumeTrue(SDK_INT != 33)
+    }
+
     @Test
     fun plainTooltip_lightTheme() {
         rule.setMaterialContent(lightColorScheme()) { PlainTooltipTest() }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ListItem.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ListItem.kt
index a770a50..ae11486 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ListItem.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ListItem.kt
@@ -207,8 +207,9 @@
     paddingValues: PaddingValues,
     content: @Composable RowScope.() -> Unit,
 ) {
+    val semanticModifier = Modifier.semantics(mergeDescendants = true) { }.then(modifier)
     Surface(
-        modifier = modifier,
+        modifier = semanticModifier,
         shape = shape,
         color = containerColor,
         contentColor = contentColor,
@@ -218,8 +219,7 @@
         Row(
             modifier = Modifier
                 .heightIn(min = minHeight)
-                .padding(paddingValues)
-                .semantics(mergeDescendants = true) {},
+                .padding(paddingValues),
             content = content
         )
     }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
index c418cf7..064586d 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
@@ -105,7 +105,7 @@
     softWrap: Boolean = true,
     maxLines: Int = Int.MAX_VALUE,
     minLines: Int = 1,
-    onTextLayout: (TextLayoutResult) -> Unit = {},
+    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
     style: TextStyle = LocalTextStyle.current
 ) {
 
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index 59a556b..3ddd28d 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -200,8 +200,8 @@
   }
 
   @androidx.compose.runtime.Stable public abstract sealed class CompositionLocal<T> {
-    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T! getCurrent();
-    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T! current;
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T getCurrent();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T current;
   }
 
   @androidx.compose.runtime.Stable public final class CompositionLocalContext {
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index 9ce9384..1bea3e6 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -218,8 +218,8 @@
   }
 
   @androidx.compose.runtime.Stable public abstract sealed class CompositionLocal<T> {
-    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T! getCurrent();
-    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T! current;
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T getCurrent();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T current;
   }
 
   @androidx.compose.runtime.Stable public final class CompositionLocalContext {
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index 366b6db..55a4ec2 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -218,8 +218,8 @@
   }
 
   @androidx.compose.runtime.Stable public abstract sealed class CompositionLocal<T> {
-    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T! getCurrent();
-    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T! current;
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T getCurrent();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final inline T current;
   }
 
   @androidx.compose.runtime.Stable public final class CompositionLocalContext {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt
index 243dc42..8f2683a 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt
@@ -28,5 +28,5 @@
      * IMPORTANT: Whenever updating this value, please make sure to also update `versionTable` and
      * `minimumRuntimeVersionInt` in `VersionChecker.kt` of the compiler.
      */
-    const val version: Int = 9901
+    const val version: Int = 10001
 }
diff --git a/compose/ui/ui-text/api/current.ignore b/compose/ui/ui-text/api/current.ignore
index 7670599..bf842f8 100644
--- a/compose/ui/ui-text/api/current.ignore
+++ b/compose/ui/ui-text/api/current.ignore
@@ -1,4 +1,10 @@
 // Baseline format: 1.0
+AddedAbstractMethod: androidx.compose.ui.text.Paragraph#paint(androidx.compose.ui.graphics.Canvas, androidx.compose.ui.graphics.Brush, float, androidx.compose.ui.graphics.Shadow, androidx.compose.ui.text.style.TextDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle, int):
+    Added method androidx.compose.ui.text.Paragraph.paint(androidx.compose.ui.graphics.Canvas,androidx.compose.ui.graphics.Brush,float,androidx.compose.ui.graphics.Shadow,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.graphics.drawscope.DrawStyle,int)
+AddedAbstractMethod: androidx.compose.ui.text.Paragraph#paint(androidx.compose.ui.graphics.Canvas, long, androidx.compose.ui.graphics.Shadow, androidx.compose.ui.text.style.TextDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle, int):
+    Added method androidx.compose.ui.text.Paragraph.paint(androidx.compose.ui.graphics.Canvas,long,androidx.compose.ui.graphics.Shadow,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.graphics.drawscope.DrawStyle,int)
+
+
 ChangedType: androidx.compose.ui.text.AnnotatedString.Builder#append(char):
     Method androidx.compose.ui.text.AnnotatedString.Builder.append has changed return type from androidx.compose.ui.text.AnnotatedString.Builder to void
 
diff --git a/compose/ui/ui-text/api/current.txt b/compose/ui/ui-text/api/current.txt
index f05e380..5851ea7 100644
--- a/compose/ui/ui-text/api/current.txt
+++ b/compose/ui/ui-text/api/current.txt
@@ -128,7 +128,9 @@
     method public float getWidth();
     method public long getWordBoundary(int offset);
     method public boolean isLineEllipsized(int lineIndex);
-    method public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method @Deprecated public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration);
     property public final boolean didExceedMaxLines;
     property public final float firstBaseline;
     property public final float height;
@@ -186,6 +188,8 @@
     method public long getWordBoundary(int offset);
     method public boolean isLineEllipsized(int lineIndex);
     method public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, float alpha, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
     property public abstract boolean didExceedMaxLines;
     property public abstract float firstBaseline;
     property public abstract float height;
@@ -220,12 +224,14 @@
   }
 
   @androidx.compose.runtime.Immutable public final class ParagraphStyle {
-    ctor public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
+    method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
     method public androidx.compose.ui.text.style.Hyphens? getHyphens();
     method public androidx.compose.ui.text.style.LineBreak? getLineBreak();
     method public long getLineHeight();
@@ -234,6 +240,7 @@
     method public androidx.compose.ui.text.style.TextAlign? getTextAlign();
     method public androidx.compose.ui.text.style.TextDirection? getTextDirection();
     method public androidx.compose.ui.text.style.TextIndent? getTextIndent();
+    method public androidx.compose.ui.text.style.TextMotion? getTextMotion();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.ParagraphStyle merge(optional androidx.compose.ui.text.ParagraphStyle? other);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.ParagraphStyle plus(androidx.compose.ui.text.ParagraphStyle other);
     property public final androidx.compose.ui.text.style.Hyphens? hyphens;
@@ -244,6 +251,7 @@
     property public final androidx.compose.ui.text.style.TextAlign? textAlign;
     property public final androidx.compose.ui.text.style.TextDirection? textDirection;
     property public final androidx.compose.ui.text.style.TextIndent? textIndent;
+    property public final androidx.compose.ui.text.style.TextMotion? textMotion;
   }
 
   public final class ParagraphStyleKt {
@@ -321,13 +329,20 @@
   }
 
   @androidx.compose.runtime.Immutable public final class SpanStyle {
-    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
-    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
-    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
-    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    ctor public SpanStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
+    ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    method public androidx.compose.ui.text.SpanStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    method @Deprecated public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
+    method @Deprecated public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    method public float getAlpha();
     method public long getBackground();
     method public androidx.compose.ui.text.style.BaselineShift? getBaselineShift();
+    method public androidx.compose.ui.graphics.Brush? getBrush();
     method public long getColor();
+    method public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
     method public String? getFontFeatureSettings();
     method public long getFontSize();
@@ -342,9 +357,12 @@
     method public androidx.compose.ui.text.style.TextGeometricTransform? getTextGeometricTransform();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.SpanStyle merge(optional androidx.compose.ui.text.SpanStyle? other);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.SpanStyle plus(androidx.compose.ui.text.SpanStyle other);
+    property public final float alpha;
     property public final long background;
     property public final androidx.compose.ui.text.style.BaselineShift? baselineShift;
+    property public final androidx.compose.ui.graphics.Brush? brush;
     property public final long color;
+    property public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
     property public final androidx.compose.ui.text.font.FontFamily? fontFamily;
     property public final String? fontFeatureSettings;
     property public final long fontSize;
@@ -455,6 +473,13 @@
     field public static final androidx.compose.ui.text.TextPainter INSTANCE;
   }
 
+  public final class TextPainterKt {
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, androidx.compose.ui.text.AnnotatedString text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.Placeholder>> placeholders, optional long size, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, String text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional long size, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, optional long color, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, androidx.compose.ui.graphics.Brush brush, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+  }
+
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TextRange {
     method public operator boolean contains(long other);
     method public operator boolean contains(int offset);
@@ -489,15 +514,22 @@
   }
 
   @androidx.compose.runtime.Immutable public final class TextStyle {
-    ctor public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    ctor public TextStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    method public androidx.compose.ui.text.TextStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
+    method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public float getAlpha();
     method public long getBackground();
     method public androidx.compose.ui.text.style.BaselineShift? getBaselineShift();
+    method public androidx.compose.ui.graphics.Brush? getBrush();
     method public long getColor();
+    method public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
     method public String? getFontFeatureSettings();
     method public long getFontSize();
@@ -517,6 +549,7 @@
     method public androidx.compose.ui.text.style.TextDirection? getTextDirection();
     method public androidx.compose.ui.text.style.TextGeometricTransform? getTextGeometricTransform();
     method public androidx.compose.ui.text.style.TextIndent? getTextIndent();
+    method public androidx.compose.ui.text.style.TextMotion? getTextMotion();
     method public boolean hasSameLayoutAffectingAttributes(androidx.compose.ui.text.TextStyle other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.TextStyle merge(optional androidx.compose.ui.text.TextStyle? other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.TextStyle merge(androidx.compose.ui.text.SpanStyle other);
@@ -526,9 +559,12 @@
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.TextStyle plus(androidx.compose.ui.text.SpanStyle other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.SpanStyle toSpanStyle();
+    property public final float alpha;
     property public final long background;
     property public final androidx.compose.ui.text.style.BaselineShift? baselineShift;
+    property public final androidx.compose.ui.graphics.Brush? brush;
     property public final long color;
+    property public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
     property public final androidx.compose.ui.text.font.FontFamily? fontFamily;
     property public final String? fontFeatureSettings;
     property public final long fontSize;
@@ -548,6 +584,7 @@
     property public final androidx.compose.ui.text.style.TextDirection? textDirection;
     property public final androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform;
     property public final androidx.compose.ui.text.style.TextIndent? textIndent;
+    property public final androidx.compose.ui.text.style.TextMotion? textMotion;
     field public static final androidx.compose.ui.text.TextStyle.Companion Companion;
   }
 
@@ -1423,6 +1460,17 @@
     method public static androidx.compose.ui.text.style.TextIndent lerp(androidx.compose.ui.text.style.TextIndent start, androidx.compose.ui.text.style.TextIndent stop, float fraction);
   }
 
+  @androidx.compose.runtime.Immutable public final class TextMotion {
+    field public static final androidx.compose.ui.text.style.TextMotion.Companion Companion;
+  }
+
+  public static final class TextMotion.Companion {
+    method public androidx.compose.ui.text.style.TextMotion getAnimated();
+    method public androidx.compose.ui.text.style.TextMotion getStatic();
+    property public final androidx.compose.ui.text.style.TextMotion Animated;
+    property public final androidx.compose.ui.text.style.TextMotion Static;
+  }
+
   @kotlin.jvm.JvmInline public final value class TextOverflow {
     field public static final androidx.compose.ui.text.style.TextOverflow.Companion Companion;
   }
diff --git a/compose/ui/ui-text/api/public_plus_experimental_current.txt b/compose/ui/ui-text/api/public_plus_experimental_current.txt
index c7477c0..d3a65c8 100644
--- a/compose/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-text/api/public_plus_experimental_current.txt
@@ -141,9 +141,9 @@
     method public float getWidth();
     method public long getWordBoundary(int offset);
     method public boolean isLineEllipsized(int lineIndex);
-    method public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration);
-    method @androidx.compose.ui.text.ExperimentalTextApi public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
-    method @androidx.compose.ui.text.ExperimentalTextApi public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method @Deprecated public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration);
     property public final boolean didExceedMaxLines;
     property public final float firstBaseline;
     property public final float height;
@@ -201,8 +201,8 @@
     method public long getWordBoundary(int offset);
     method public boolean isLineEllipsized(int lineIndex);
     method public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration);
-    method @androidx.compose.ui.text.ExperimentalTextApi public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
-    method @androidx.compose.ui.text.ExperimentalTextApi public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, float alpha, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, float alpha, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
     property public abstract boolean didExceedMaxLines;
     property public abstract float firstBaseline;
     property public abstract float height;
@@ -237,14 +237,14 @@
   }
 
   @androidx.compose.runtime.Immutable public final class ParagraphStyle {
-    ctor @androidx.compose.ui.text.ExperimentalTextApi public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
-    ctor public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
+    method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
     method public androidx.compose.ui.text.style.Hyphens? getHyphens();
     method public androidx.compose.ui.text.style.LineBreak? getLineBreak();
     method public long getLineHeight();
@@ -253,7 +253,7 @@
     method public androidx.compose.ui.text.style.TextAlign? getTextAlign();
     method public androidx.compose.ui.text.style.TextDirection? getTextDirection();
     method public androidx.compose.ui.text.style.TextIndent? getTextIndent();
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.style.TextMotion? getTextMotion();
+    method public androidx.compose.ui.text.style.TextMotion? getTextMotion();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.ParagraphStyle merge(optional androidx.compose.ui.text.ParagraphStyle? other);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.ParagraphStyle plus(androidx.compose.ui.text.ParagraphStyle other);
     property public final androidx.compose.ui.text.style.Hyphens? hyphens;
@@ -264,7 +264,7 @@
     property public final androidx.compose.ui.text.style.TextAlign? textAlign;
     property public final androidx.compose.ui.text.style.TextDirection? textDirection;
     property public final androidx.compose.ui.text.style.TextIndent? textIndent;
-    property @androidx.compose.ui.text.ExperimentalTextApi public final androidx.compose.ui.text.style.TextMotion? textMotion;
+    property public final androidx.compose.ui.text.style.TextMotion? textMotion;
   }
 
   public final class ParagraphStyleKt {
@@ -342,20 +342,20 @@
   }
 
   @androidx.compose.runtime.Immutable public final class SpanStyle {
-    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
-    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
-    ctor @androidx.compose.ui.text.ExperimentalTextApi public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
-    ctor @androidx.compose.ui.text.ExperimentalTextApi public SpanStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
-    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
-    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.SpanStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
-    method @androidx.compose.ui.text.ExperimentalTextApi public float getAlpha();
+    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    ctor public SpanStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
+    ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    method public androidx.compose.ui.text.SpanStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    method @Deprecated public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
+    method @Deprecated public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    method public float getAlpha();
     method public long getBackground();
     method public androidx.compose.ui.text.style.BaselineShift? getBaselineShift();
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.graphics.Brush? getBrush();
+    method public androidx.compose.ui.graphics.Brush? getBrush();
     method public long getColor();
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
+    method public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
     method public String? getFontFeatureSettings();
     method public long getFontSize();
@@ -370,12 +370,12 @@
     method public androidx.compose.ui.text.style.TextGeometricTransform? getTextGeometricTransform();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.SpanStyle merge(optional androidx.compose.ui.text.SpanStyle? other);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.SpanStyle plus(androidx.compose.ui.text.SpanStyle other);
-    property @androidx.compose.ui.text.ExperimentalTextApi public final float alpha;
+    property public final float alpha;
     property public final long background;
     property public final androidx.compose.ui.text.style.BaselineShift? baselineShift;
-    property @androidx.compose.ui.text.ExperimentalTextApi public final androidx.compose.ui.graphics.Brush? brush;
+    property public final androidx.compose.ui.graphics.Brush? brush;
     property public final long color;
-    property @androidx.compose.ui.text.ExperimentalTextApi public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
+    property public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
     property public final androidx.compose.ui.text.font.FontFamily? fontFamily;
     property public final String? fontFeatureSettings;
     property public final long fontSize;
@@ -487,10 +487,10 @@
   }
 
   public final class TextPainterKt {
-    method @androidx.compose.ui.text.ExperimentalTextApi public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, androidx.compose.ui.text.AnnotatedString text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.Placeholder>> placeholders, optional long size, optional int blendMode);
-    method @androidx.compose.ui.text.ExperimentalTextApi public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, String text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional long size, optional int blendMode);
-    method @androidx.compose.ui.text.ExperimentalTextApi public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, optional long color, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
-    method @androidx.compose.ui.text.ExperimentalTextApi public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, androidx.compose.ui.graphics.Brush brush, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, androidx.compose.ui.text.AnnotatedString text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.Placeholder>> placeholders, optional long size, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, String text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional long size, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, optional long color, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, androidx.compose.ui.graphics.Brush brush, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TextRange {
@@ -527,22 +527,22 @@
   }
 
   @androidx.compose.runtime.Immutable public final class TextStyle {
-    ctor public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
-    ctor @androidx.compose.ui.text.ExperimentalTextApi public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
-    ctor @androidx.compose.ui.text.ExperimentalTextApi public TextStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    ctor public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    ctor public TextStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.TextStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    method public androidx.compose.ui.text.TextStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method @androidx.compose.ui.text.ExperimentalTextApi public float getAlpha();
+    method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public float getAlpha();
     method public long getBackground();
     method public androidx.compose.ui.text.style.BaselineShift? getBaselineShift();
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.graphics.Brush? getBrush();
+    method public androidx.compose.ui.graphics.Brush? getBrush();
     method public long getColor();
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
+    method public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
     method public String? getFontFeatureSettings();
     method public long getFontSize();
@@ -562,7 +562,7 @@
     method public androidx.compose.ui.text.style.TextDirection? getTextDirection();
     method public androidx.compose.ui.text.style.TextGeometricTransform? getTextGeometricTransform();
     method public androidx.compose.ui.text.style.TextIndent? getTextIndent();
-    method @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.style.TextMotion? getTextMotion();
+    method public androidx.compose.ui.text.style.TextMotion? getTextMotion();
     method public boolean hasSameLayoutAffectingAttributes(androidx.compose.ui.text.TextStyle other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.TextStyle merge(optional androidx.compose.ui.text.TextStyle? other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.TextStyle merge(androidx.compose.ui.text.SpanStyle other);
@@ -572,12 +572,12 @@
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.TextStyle plus(androidx.compose.ui.text.SpanStyle other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.SpanStyle toSpanStyle();
-    property @androidx.compose.ui.text.ExperimentalTextApi public final float alpha;
+    property public final float alpha;
     property public final long background;
     property public final androidx.compose.ui.text.style.BaselineShift? baselineShift;
-    property @androidx.compose.ui.text.ExperimentalTextApi public final androidx.compose.ui.graphics.Brush? brush;
+    property public final androidx.compose.ui.graphics.Brush? brush;
     property public final long color;
-    property @androidx.compose.ui.text.ExperimentalTextApi public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
+    property public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
     property public final androidx.compose.ui.text.font.FontFamily? fontFamily;
     property public final String? fontFeatureSettings;
     property public final long fontSize;
@@ -597,7 +597,7 @@
     property public final androidx.compose.ui.text.style.TextDirection? textDirection;
     property public final androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform;
     property public final androidx.compose.ui.text.style.TextIndent? textIndent;
-    property @androidx.compose.ui.text.ExperimentalTextApi public final androidx.compose.ui.text.style.TextMotion? textMotion;
+    property public final androidx.compose.ui.text.style.TextMotion? textMotion;
     field public static final androidx.compose.ui.text.TextStyle.Companion Companion;
   }
 
@@ -1515,7 +1515,7 @@
     method public static androidx.compose.ui.text.style.TextIndent lerp(androidx.compose.ui.text.style.TextIndent start, androidx.compose.ui.text.style.TextIndent stop, float fraction);
   }
 
-  @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public final class TextMotion {
+  @androidx.compose.runtime.Immutable public final class TextMotion {
     field public static final androidx.compose.ui.text.style.TextMotion.Companion Companion;
   }
 
diff --git a/compose/ui/ui-text/api/restricted_current.ignore b/compose/ui/ui-text/api/restricted_current.ignore
index 7670599..bf842f8 100644
--- a/compose/ui/ui-text/api/restricted_current.ignore
+++ b/compose/ui/ui-text/api/restricted_current.ignore
@@ -1,4 +1,10 @@
 // Baseline format: 1.0
+AddedAbstractMethod: androidx.compose.ui.text.Paragraph#paint(androidx.compose.ui.graphics.Canvas, androidx.compose.ui.graphics.Brush, float, androidx.compose.ui.graphics.Shadow, androidx.compose.ui.text.style.TextDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle, int):
+    Added method androidx.compose.ui.text.Paragraph.paint(androidx.compose.ui.graphics.Canvas,androidx.compose.ui.graphics.Brush,float,androidx.compose.ui.graphics.Shadow,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.graphics.drawscope.DrawStyle,int)
+AddedAbstractMethod: androidx.compose.ui.text.Paragraph#paint(androidx.compose.ui.graphics.Canvas, long, androidx.compose.ui.graphics.Shadow, androidx.compose.ui.text.style.TextDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle, int):
+    Added method androidx.compose.ui.text.Paragraph.paint(androidx.compose.ui.graphics.Canvas,long,androidx.compose.ui.graphics.Shadow,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.graphics.drawscope.DrawStyle,int)
+
+
 ChangedType: androidx.compose.ui.text.AnnotatedString.Builder#append(char):
     Method androidx.compose.ui.text.AnnotatedString.Builder.append has changed return type from androidx.compose.ui.text.AnnotatedString.Builder to void
 
diff --git a/compose/ui/ui-text/api/restricted_current.txt b/compose/ui/ui-text/api/restricted_current.txt
index f05e380..5851ea7 100644
--- a/compose/ui/ui-text/api/restricted_current.txt
+++ b/compose/ui/ui-text/api/restricted_current.txt
@@ -128,7 +128,9 @@
     method public float getWidth();
     method public long getWordBoundary(int offset);
     method public boolean isLineEllipsized(int lineIndex);
-    method public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method @Deprecated public void paint(androidx.compose.ui.graphics.Canvas canvas, optional long color, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? decoration);
     property public final boolean didExceedMaxLines;
     property public final float firstBaseline;
     property public final float height;
@@ -186,6 +188,8 @@
     method public long getWordBoundary(int offset);
     method public boolean isLineEllipsized(int lineIndex);
     method public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, long color, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
+    method public void paint(androidx.compose.ui.graphics.Canvas canvas, androidx.compose.ui.graphics.Brush brush, float alpha, androidx.compose.ui.graphics.Shadow? shadow, androidx.compose.ui.text.style.TextDecoration? textDecoration, androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, int blendMode);
     property public abstract boolean didExceedMaxLines;
     property public abstract float firstBaseline;
     property public abstract float height;
@@ -220,12 +224,14 @@
   }
 
   @androidx.compose.runtime.Immutable public final class ParagraphStyle {
-    ctor public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
+    method @Deprecated public androidx.compose.ui.text.ParagraphStyle copy(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
     method public androidx.compose.ui.text.style.Hyphens? getHyphens();
     method public androidx.compose.ui.text.style.LineBreak? getLineBreak();
     method public long getLineHeight();
@@ -234,6 +240,7 @@
     method public androidx.compose.ui.text.style.TextAlign? getTextAlign();
     method public androidx.compose.ui.text.style.TextDirection? getTextDirection();
     method public androidx.compose.ui.text.style.TextIndent? getTextIndent();
+    method public androidx.compose.ui.text.style.TextMotion? getTextMotion();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.ParagraphStyle merge(optional androidx.compose.ui.text.ParagraphStyle? other);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.ParagraphStyle plus(androidx.compose.ui.text.ParagraphStyle other);
     property public final androidx.compose.ui.text.style.Hyphens? hyphens;
@@ -244,6 +251,7 @@
     property public final androidx.compose.ui.text.style.TextAlign? textAlign;
     property public final androidx.compose.ui.text.style.TextDirection? textDirection;
     property public final androidx.compose.ui.text.style.TextIndent? textIndent;
+    property public final androidx.compose.ui.text.style.TextMotion? textMotion;
   }
 
   public final class ParagraphStyleKt {
@@ -321,13 +329,20 @@
   }
 
   @androidx.compose.runtime.Immutable public final class SpanStyle {
-    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
-    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
-    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
-    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    ctor public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    ctor public SpanStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
+    ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    method public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    method public androidx.compose.ui.text.SpanStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
+    method @Deprecated public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
+    method @Deprecated public androidx.compose.ui.text.SpanStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
+    method public float getAlpha();
     method public long getBackground();
     method public androidx.compose.ui.text.style.BaselineShift? getBaselineShift();
+    method public androidx.compose.ui.graphics.Brush? getBrush();
     method public long getColor();
+    method public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
     method public String? getFontFeatureSettings();
     method public long getFontSize();
@@ -342,9 +357,12 @@
     method public androidx.compose.ui.text.style.TextGeometricTransform? getTextGeometricTransform();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.SpanStyle merge(optional androidx.compose.ui.text.SpanStyle? other);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.SpanStyle plus(androidx.compose.ui.text.SpanStyle other);
+    property public final float alpha;
     property public final long background;
     property public final androidx.compose.ui.text.style.BaselineShift? baselineShift;
+    property public final androidx.compose.ui.graphics.Brush? brush;
     property public final long color;
+    property public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
     property public final androidx.compose.ui.text.font.FontFamily? fontFamily;
     property public final String? fontFeatureSettings;
     property public final long fontSize;
@@ -455,6 +473,13 @@
     field public static final androidx.compose.ui.text.TextPainter INSTANCE;
   }
 
+  public final class TextPainterKt {
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, androidx.compose.ui.text.AnnotatedString text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.Placeholder>> placeholders, optional long size, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextMeasurer textMeasurer, String text, optional long topLeft, optional androidx.compose.ui.text.TextStyle style, optional int overflow, optional boolean softWrap, optional int maxLines, optional long size, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, optional long color, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+    method public static void drawText(androidx.compose.ui.graphics.drawscope.DrawScope, androidx.compose.ui.text.TextLayoutResult textLayoutResult, androidx.compose.ui.graphics.Brush brush, optional long topLeft, optional float alpha, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional int blendMode);
+  }
+
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TextRange {
     method public operator boolean contains(long other);
     method public operator boolean contains(int offset);
@@ -489,15 +514,22 @@
   }
 
   @androidx.compose.runtime.Immutable public final class TextStyle {
-    ctor public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    ctor public TextStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
-    method public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    ctor @Deprecated public TextStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
+    method public androidx.compose.ui.text.TextStyle copy(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens, optional androidx.compose.ui.text.style.TextMotion? textMotion);
     method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
+    method @Deprecated public androidx.compose.ui.text.TextStyle copy(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformTextStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
+    method public float getAlpha();
     method public long getBackground();
     method public androidx.compose.ui.text.style.BaselineShift? getBaselineShift();
+    method public androidx.compose.ui.graphics.Brush? getBrush();
     method public long getColor();
+    method public androidx.compose.ui.graphics.drawscope.DrawStyle? getDrawStyle();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
     method public String? getFontFeatureSettings();
     method public long getFontSize();
@@ -517,6 +549,7 @@
     method public androidx.compose.ui.text.style.TextDirection? getTextDirection();
     method public androidx.compose.ui.text.style.TextGeometricTransform? getTextGeometricTransform();
     method public androidx.compose.ui.text.style.TextIndent? getTextIndent();
+    method public androidx.compose.ui.text.style.TextMotion? getTextMotion();
     method public boolean hasSameLayoutAffectingAttributes(androidx.compose.ui.text.TextStyle other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.TextStyle merge(optional androidx.compose.ui.text.TextStyle? other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.TextStyle merge(androidx.compose.ui.text.SpanStyle other);
@@ -526,9 +559,12 @@
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.TextStyle plus(androidx.compose.ui.text.SpanStyle other);
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.runtime.Stable public androidx.compose.ui.text.SpanStyle toSpanStyle();
+    property public final float alpha;
     property public final long background;
     property public final androidx.compose.ui.text.style.BaselineShift? baselineShift;
+    property public final androidx.compose.ui.graphics.Brush? brush;
     property public final long color;
+    property public final androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle;
     property public final androidx.compose.ui.text.font.FontFamily? fontFamily;
     property public final String? fontFeatureSettings;
     property public final long fontSize;
@@ -548,6 +584,7 @@
     property public final androidx.compose.ui.text.style.TextDirection? textDirection;
     property public final androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform;
     property public final androidx.compose.ui.text.style.TextIndent? textIndent;
+    property public final androidx.compose.ui.text.style.TextMotion? textMotion;
     field public static final androidx.compose.ui.text.TextStyle.Companion Companion;
   }
 
@@ -1423,6 +1460,17 @@
     method public static androidx.compose.ui.text.style.TextIndent lerp(androidx.compose.ui.text.style.TextIndent start, androidx.compose.ui.text.style.TextIndent stop, float fraction);
   }
 
+  @androidx.compose.runtime.Immutable public final class TextMotion {
+    field public static final androidx.compose.ui.text.style.TextMotion.Companion Companion;
+  }
+
+  public static final class TextMotion.Companion {
+    method public androidx.compose.ui.text.style.TextMotion getAnimated();
+    method public androidx.compose.ui.text.style.TextMotion getStatic();
+    property public final androidx.compose.ui.text.style.TextMotion Animated;
+    property public final androidx.compose.ui.text.style.TextMotion Static;
+  }
+
   @kotlin.jvm.JvmInline public final value class TextOverflow {
     field public static final androidx.compose.ui.text.style.TextOverflow.Companion Companion;
   }
diff --git a/compose/ui/ui-text/benchmark/src/androidTest/java/androidx/compose/ui/text/benchmark/TextMeasurerBenchmark.kt b/compose/ui/ui-text/benchmark/src/androidTest/java/androidx/compose/ui/text/benchmark/TextMeasurerBenchmark.kt
index 3a5ebaf..993ebf5 100644
--- a/compose/ui/ui-text/benchmark/src/androidTest/java/androidx/compose/ui/text/benchmark/TextMeasurerBenchmark.kt
+++ b/compose/ui/ui-text/benchmark/src/androidTest/java/androidx/compose/ui/text/benchmark/TextMeasurerBenchmark.kt
@@ -25,7 +25,6 @@
 import androidx.compose.ui.graphics.ImageBitmap
 import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
 import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.TextMeasurer
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.drawText
@@ -44,7 +43,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-@OptIn(ExperimentalTextApi::class)
 @LargeTest
 @RunWith(Parameterized::class)
 class TextMeasurerBenchmark(
@@ -94,7 +92,6 @@
         return AnnotatedString(text = text, spanStyles = spanStyles)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun text_measurer_no_cache() {
         textBenchmarkRule.generator { textGenerator ->
@@ -115,7 +112,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun text_measurer_cached() {
         textBenchmarkRule.generator { textGenerator ->
@@ -136,7 +132,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun drawText_TextLayoutResult_no_change() {
         textBenchmarkRule.generator { textGenerator ->
@@ -168,7 +163,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun drawText_TextLayoutResult_color_override() {
         textBenchmarkRule.generator { textGenerator ->
diff --git a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/DrawTextSamples.kt b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/DrawTextSamples.kt
index e655120..2a7f037 100644
--- a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/DrawTextSamples.kt
+++ b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/DrawTextSamples.kt
@@ -27,14 +27,12 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.drawText
 import androidx.compose.ui.text.rememberTextMeasurer
 import androidx.compose.ui.unit.sp
 
-@OptIn(ExperimentalTextApi::class)
 @Sampled
 @Composable
 fun DrawTextLayoutResultSample() {
diff --git a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/SpanStyleSamples.kt b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/SpanStyleSamples.kt
index 88619248..15918fb 100644
--- a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/SpanStyleSamples.kt
+++ b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/SpanStyleSamples.kt
@@ -21,7 +21,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.buildAnnotatedString
 import androidx.compose.ui.text.withStyle
@@ -43,7 +42,6 @@
     )
 }
 
-@OptIn(ExperimentalTextApi::class)
 @Sampled
 @Composable
 fun SpanStyleBrushSample() {
diff --git a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/TextStyleSamples.kt b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/TextStyleSamples.kt
index 2742cdc..2950317 100644
--- a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/TextStyleSamples.kt
+++ b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/TextStyleSamples.kt
@@ -21,7 +21,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontStyle
@@ -48,7 +47,6 @@
     )
 }
 
-@OptIn(ExperimentalTextApi::class)
 @Sampled
 @Composable
 fun TextStyleBrushSample() {
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/AndroidParagraphTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/AndroidParagraphTest.kt
index 0a5a040..386b478 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/AndroidParagraphTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/AndroidParagraphTest.kt
@@ -175,7 +175,6 @@
         assertThat(paragraph.charSequence).hasSpanOnTop(ForegroundColorSpan::class, 0, "abc".length)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testAnnotatedString_setBrushOnWholeText() {
         val text = "abcde"
@@ -193,7 +192,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testAnnotatedString_setSolidColorBrushOnWholeText() {
         val text = "abcde"
@@ -209,7 +207,6 @@
         assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, text.length)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testAnnotatedString_setBrushOnPartOfText() {
         val text = "abcde"
@@ -227,7 +224,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testAnnotatedString_brushSpanReceivesSize() {
         with(defaultDensity) {
@@ -909,7 +905,6 @@
             }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testAnnotatedString_setDrawStyle() {
         val text = "abcde"
@@ -943,7 +938,6 @@
             }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testAnnotatedString_setDrawStyle_FillOnTopOfStroke() {
         val text = "abcde"
@@ -1348,7 +1342,6 @@
         assertThat(paragraph.textPaint.color).isEqualTo(color.toArgb())
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testSpanStyle_brush_appliedOnTextPaint() {
         val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue)) as ShaderBrush
@@ -1485,7 +1478,6 @@
         assertThat(paragraph.textPaint.isStrikeThruText).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testSpanStyle_drawStyle_stroke_appliedOnTextPaint() {
         val paragraph = simpleParagraph(
@@ -1506,7 +1498,6 @@
         assertThat(paragraph.textPaint.strokeJoin).isEqualTo(Paint.Join.BEVEL)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testSpanStyle_drawStyle_fill_appliedOnTextPaint() {
         val paragraph = simpleParagraph(
@@ -1582,7 +1573,6 @@
         assertThat(paragraph.textPaint.isUnderlineText).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testPaint_can_change_DrawStyle_to_Stroke() {
         val paragraph = simpleParagraph(
@@ -1603,7 +1593,6 @@
         assertThat(paragraph.textPaint.strokeJoin).isEqualTo(Paint.Join.BEVEL)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testPaint_can_change_DrawStyle_to_Fill() {
         val paragraph = simpleParagraph(
@@ -1619,7 +1608,6 @@
         assertThat(paragraph.textPaint.style).isEqualTo(Paint.Style.FILL)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testPaint_null_drawStyle_should_be_noop() {
         val paragraph = simpleParagraph(
@@ -1984,7 +1972,6 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun shaderBrushSpan_createsShaderOnlyOnce() {
         val fontSize = 20
@@ -2042,7 +2029,6 @@
         assertThat(bitmapWithSpan).isEqualToBitmap(bitmapNoSpan)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun textMotionStatic_setsCorrectFlagsOnTextPaint() {
         val textMotion = TextMotion.Static
@@ -2058,7 +2044,6 @@
         assertThat(paragraph.textPaint.hinting).isEqualTo(TextPaint.HINTING_ON)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun textMotionAnimated_setsCorrectFlagsOnTextPaint() {
         val textMotion = TextMotion.Animated
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/CacheTextLayoutInputTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/CacheTextLayoutInputTest.kt
index d377ab3..43d704c 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/CacheTextLayoutInputTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/CacheTextLayoutInputTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import androidx.compose.ui.geometry.Offset
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/MultiParagraphIntegrationTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/MultiParagraphIntegrationTest.kt
index efe1944..10b709b 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/MultiParagraphIntegrationTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/MultiParagraphIntegrationTest.kt
@@ -1512,7 +1512,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun multiParagraph_appliesBrush_toTheWholeText() = with(defaultDensity) {
         val fontSize = 20.sp
@@ -1550,7 +1549,6 @@
             .isEqualToBitmap(multiParagraph2.bitmap(brush))
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun multiParagraph_overridesAlphaDuringDraw() = with(defaultDensity) {
         val fontSize = 20.sp
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationTest.kt
index c2fe639..1b3119b 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationTest.kt
@@ -3740,7 +3740,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testDefaultSpanStyle_setBrush() {
         with(defaultDensity) {
@@ -3770,7 +3769,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testDefaultSpanStyle_setBrushAlpha() {
         with(defaultDensity) {
@@ -3802,7 +3800,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testDefaultSpanStyle_overrideAlphaDuringDraw() {
         with(defaultDensity) {
@@ -4366,7 +4363,6 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testSolidBrushColorIsSameAsColor() {
         with(defaultDensity) {
@@ -4393,7 +4389,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testSpanBrush_overridesDefaultBrush() {
         with(defaultDensity) {
@@ -4435,7 +4430,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testBrush_notEffectedBy_TextDirection() {
         with(defaultDensity) {
@@ -4518,7 +4512,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun paint_withBlendMode_changesVisual() {
         with(defaultDensity) {
@@ -4554,7 +4547,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun paint_withBlendMode_sameResult() {
         with(defaultDensity) {
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformParagraphStyleTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformParagraphStyleTest.kt
index b0feae1..09d8375 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformParagraphStyleTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformParagraphStyleTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import com.google.common.truth.Truth.assertThat
@@ -23,7 +21,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
-@Suppress("DEPRECATION")
 @RunWith(JUnit4::class)
 class PlatformParagraphStyleTest {
 
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformSpanStyleTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformSpanStyleTest.kt
index ae7baff..ef9afe5 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformSpanStyleTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformSpanStyleTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import com.google.common.truth.Truth.assertThat
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformTextStyleTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformTextStyleTest.kt
index a51ee71..8aa22e0 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformTextStyleTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/PlatformTextStyleTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import com.google.common.truth.Truth.assertThat
@@ -23,7 +21,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
-@Suppress("DEPRECATION")
 @RunWith(JUnit4::class)
 class PlatformTextStyleTest {
 
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextLayoutCacheTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextLayoutCacheTest.kt
index f025c2f..14984f1 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextLayoutCacheTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextLayoutCacheTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import androidx.compose.ui.graphics.Brush
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextMeasurerTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextMeasurerTest.kt
index 37667e3..dcbf9bb 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextMeasurerTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextMeasurerTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import androidx.compose.ui.graphics.Brush
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextPainterTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextPainterTest.kt
index 3eb5285..af0ce0e3 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextPainterTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextPainterTest.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalTextApi::class)
-
 package androidx.compose.ui.text
 
 import android.graphics.Bitmap
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextTestExtensions.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextTestExtensions.kt
index d629400..102ce80a 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextTestExtensions.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/TextTestExtensions.kt
@@ -73,7 +73,6 @@
     return bitmap
 }
 
-@OptIn(ExperimentalTextApi::class)
 fun Paragraph.bitmap(
     color: Color = Color.Unspecified,
     shadow: Shadow? = null,
@@ -93,7 +92,6 @@
     }
 }
 
-@OptIn(ExperimentalTextApi::class)
 fun Paragraph.bitmap(
     brush: Brush,
     alpha: Float,
@@ -123,7 +121,6 @@
  * We have to re-specify the brush during paint(draw) to apply it according to the total size of
  * MultiParagraph.
  */
-@OptIn(ExperimentalTextApi::class)
 fun MultiParagraph.bitmap(
     brush: Brush? = null,
     alpha: Float = Float.NaN,
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterTest.kt
index 26b1954..b6168c47 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterTest.kt
@@ -102,7 +102,6 @@
         fontLoader.cacheKey
     )
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun onResolve_onlyBlockingFonts_doesNotLoad() {
         val expected = Typeface.MONOSPACE
@@ -117,7 +116,6 @@
         assertThat(result).isImmutableTypefaceOf(expected)
     }
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun onResolve_blockingAndAsyncFonts_matchesBlocking_doesLoad() {
         val expected = Typeface.MONOSPACE
@@ -365,7 +363,6 @@
         )
     }
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun onResolve_optionalAndAsyncFonts_matchesOptional_doesLoad() {
         val expected = Typeface.MONOSPACE
@@ -470,7 +467,6 @@
         scope.advanceUntilIdle()
     }
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun onResolve_optionalAndAsyncAndBlockingFonts_matchesOptional_doesNotLoadBlockingAsync() {
         val asyncFont = AsyncFauxFont(typefaceLoader)
@@ -689,7 +685,6 @@
         requestAndCompleteOnRealDispatcher()
     }
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun runtimeExceptionOnRealDispatcher_informsExceptionHandler() {
         val exception: CompletableDeferred<Throwable> = CompletableDeferred()
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/testutils/AsyncTestFonts.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/testutils/AsyncTestFonts.kt
index 0c3455e..9f24373 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/testutils/AsyncTestFonts.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/testutils/AsyncTestFonts.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.graphics.Typeface
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.font.AndroidFont
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontLoadingStrategy.Companion.Async
@@ -156,7 +155,6 @@
     }
 }
 
-@OptIn(ExperimentalTextApi::class)
 class BlockingFauxFont(
     typefaceLoader: AsyncTestTypefaceLoader,
     internal val typeface: Typeface,
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/SpannableExtensionsTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/SpannableExtensionsTest.kt
index 576b5339..2ec8bcb 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/SpannableExtensionsTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/SpannableExtensionsTest.kt
@@ -24,7 +24,6 @@
 import androidx.compose.ui.graphics.SolidColor
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontStyle
@@ -37,6 +36,9 @@
 import androidx.compose.ui.unit.sp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.kotlin.any
 import org.mockito.kotlin.argThat
 import org.mockito.kotlin.eq
@@ -45,9 +47,6 @@
 import org.mockito.kotlin.never
 import org.mockito.kotlin.times
 import org.mockito.kotlin.verify
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
@@ -505,7 +504,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun shaderBrush_shouldAdd_shaderBrushSpan_whenApplied() {
         val text = "abcde abcde"
@@ -524,7 +522,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun shaderBrush_shouldAdd_shaderBrushSpan_whenApplied_withSpecifiedAlpha() {
         val text = "abcde abcde"
@@ -543,7 +540,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun solidColorBrush_shouldAdd_ForegroundColorSpan_whenApplied() {
         val text = "abcde abcde"
@@ -557,7 +553,6 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun whenColorAndShaderBrushSpansCollide_bothShouldApply() {
         val text = "abcde abcde"
@@ -581,7 +576,6 @@
         assertThat(spannable).hasSpan(ForegroundColorSpan::class, 0, text.length)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun whenColorAndSolidColorBrushSpansCollide_bothShouldApply() {
         val text = "abcde abcde"
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/TextPaintExtensionsTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/TextPaintExtensionsTest.kt
index 70890ed..b7cdc5e3 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/TextPaintExtensionsTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/TextPaintExtensionsTest.kt
@@ -22,7 +22,6 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shadow
 import androidx.compose.ui.graphics.toArgb
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontStyle
@@ -355,7 +354,6 @@
         assertThat(notApplied?.color).isEqualTo(Color.Unspecified)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun setTextMotion_setsCorrectFlags_forLinearAndSubpixel() {
         val textMotion = TextMotion(TextMotion.Linearity.Linear, true)
@@ -369,7 +367,6 @@
         assertThat(tp.hinting).isEqualTo(TextPaint.HINTING_OFF)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun setTextMotion_setsCorrectFlags_forFontHintingAndSubpixel() {
         val textMotion = TextMotion(TextMotion.Linearity.FontHinting, true)
@@ -383,7 +380,6 @@
         assertThat(tp.hinting).isEqualTo(TextPaint.HINTING_ON)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun setTextMotion_setsCorrectFlags_forNoneAndSubpixel() {
         val textMotion = TextMotion(TextMotion.Linearity.None, true)
@@ -397,7 +393,6 @@
         assertThat(tp.hinting).isEqualTo(TextPaint.HINTING_OFF)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun setTextMotion_setsCorrectFlags_forLinear() {
         val textMotion = TextMotion(TextMotion.Linearity.Linear, false)
@@ -409,7 +404,6 @@
         assertThat(tp.hinting).isEqualTo(TextPaint.HINTING_OFF)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun setTextMotion_setsCorrectFlags_forFontHinting() {
         val textMotion = TextMotion(TextMotion.Linearity.FontHinting, false)
@@ -421,7 +415,6 @@
         assertThat(tp.hinting).isEqualTo(TextPaint.HINTING_ON)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun setTextMotion_setsCorrectFlags_forNone() {
         val textMotion = TextMotion(TextMotion.Linearity.None, false)
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/AndroidParagraph.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/AndroidParagraph.android.kt
index 3aff906..35b572e 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/AndroidParagraph.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/AndroidParagraph.android.kt
@@ -459,7 +459,6 @@
         paint(canvas)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun paint(
         canvas: Canvas,
         color: Color,
@@ -482,7 +481,6 @@
         textPaint.blendMode = currBlendMode
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun paint(
         canvas: Canvas,
         brush: Brush,
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Paragraph.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Paragraph.android.kt
index 7bbfe8d..83ba3cb 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Paragraph.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Paragraph.android.kt
@@ -58,7 +58,6 @@
     actual fun getBoundingBox(offset: Int): Rect
     actual fun getWordBoundary(offset: Int): TextRange
     actual fun paint(canvas: Canvas, color: Color, shadow: Shadow?, textDecoration: TextDecoration?)
-    @ExperimentalTextApi
     actual fun paint(
         canvas: Canvas,
         color: Color,
@@ -67,7 +66,6 @@
         drawStyle: DrawStyle?,
         blendMode: BlendMode
     )
-    @ExperimentalTextApi
     actual fun paint(
         canvas: Canvas,
         brush: Brush,
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidMultiParagraphDraw.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidMultiParagraphDraw.kt
index e88267d..0b86686 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidMultiParagraphDraw.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidMultiParagraphDraw.kt
@@ -25,12 +25,10 @@
 import androidx.compose.ui.graphics.Shadow
 import androidx.compose.ui.graphics.SolidColor
 import androidx.compose.ui.graphics.drawscope.DrawStyle
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.MultiParagraph
 import androidx.compose.ui.text.style.TextDecoration
 import androidx.compose.ui.util.fastForEach
 
-@OptIn(ExperimentalTextApi::class)
 internal actual fun MultiParagraph.drawMultiParagraph(
     canvas: Canvas,
     brush: Brush,
@@ -80,7 +78,6 @@
     canvas.restore()
 }
 
-@OptIn(ExperimentalTextApi::class)
 private fun MultiParagraph.drawParagraphs(
     canvas: Canvas,
     brush: Brush,
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt
index 3bcd60e..2fd7809 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt
@@ -23,7 +23,6 @@
 import android.text.style.CharacterStyle
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.DefaultIncludeFontPadding
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.Placeholder
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
@@ -44,7 +43,7 @@
 import androidx.compose.ui.unit.isUnspecified
 import androidx.emoji2.text.EmojiCompat
 
-@OptIn(InternalPlatformTextApi::class, ExperimentalTextApi::class)
+@OptIn(InternalPlatformTextApi::class)
 internal fun createCharSequence(
     text: String,
     contextFontSize: Float,
@@ -118,8 +117,6 @@
     return spannableString
 }
 
-@OptIn(ExperimentalTextApi::class)
-@Suppress("DEPRECATION")
 internal fun TextStyle.isIncludeFontPaddingEnabled(): Boolean {
     return platformStyle?.paragraphStyle?.includeFontPadding ?: DefaultIncludeFontPadding
 }
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt
index 3b316c8..972b324 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt
@@ -215,7 +215,6 @@
     }
 }
 
-@OptIn(ExperimentalTextApi::class)
 private fun Spannable.setSpanStyle(
     spanStyleRange: AnnotatedString.Range<SpanStyle>,
     density: Density
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.android.kt
index b92b9c55..ee6daab 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.android.kt
@@ -21,7 +21,6 @@
 import android.text.TextPaint
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontStyle
@@ -44,7 +43,6 @@
  * regular platform spans such as background, baselineShift. This function also returns a new
  * SpanStyle that consists of attributes that were not applied to the TextPaint.
  */
-@OptIn(ExperimentalTextApi::class)
 internal fun AndroidTextPaint.applySpanStyle(
     style: SpanStyle,
     resolveTypeface: (FontFamily?, FontWeight, FontStyle, FontSynthesis) -> Typeface,
@@ -154,7 +152,6 @@
     }
 }
 
-@OptIn(ExperimentalTextApi::class)
 internal fun AndroidTextPaint.setTextMotion(textMotion: TextMotion?) {
     val finalTextMotion = textMotion ?: TextMotion.Static
     flags = if (finalTextMotion.subpixelTextPositioning) {
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/TextMotion.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/TextMotion.android.kt
index e4434ce..c508974 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/TextMotion.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/TextMotion.android.kt
@@ -17,12 +17,10 @@
 package androidx.compose.ui.text.style
 
 import androidx.compose.runtime.Immutable
-import androidx.compose.ui.text.ExperimentalTextApi
 
 /**
  * Implementation of possible TextMotion configurations on Android.
  */
-@ExperimentalTextApi
 @Immutable
 actual class TextMotion internal constructor(
     internal val linearity: Linearity,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt
index dc32ce8..c0fb6f3 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt
@@ -385,6 +385,10 @@
     }
 
     /** Paint the paragraphs to canvas. */
+    @Deprecated(
+        "Use the new paint function that takes canvas as the only required parameter.",
+        level = DeprecationLevel.HIDDEN
+    )
     fun paint(
         canvas: Canvas,
         color: Color = Color.Unspecified,
@@ -400,7 +404,6 @@
     }
 
     /** Paint the paragraphs to canvas. */
-    @ExperimentalTextApi
     fun paint(
         canvas: Canvas,
         color: Color = Color.Unspecified,
@@ -418,7 +421,6 @@
     }
 
     /** Paint the paragraphs to canvas. */
-    @ExperimentalTextApi
     fun paint(
         canvas: Canvas,
         brush: Brush,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt
index 9b24ca1..b3653ef 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt
@@ -254,6 +254,10 @@
      * TextDecoration on this paragraph, `null` does not change the currently set [TextDecoration]
      * configuration.
      */
+    @Deprecated(
+        "Use the new paint function that takes canvas as the only required parameter.",
+        level = DeprecationLevel.HIDDEN
+    )
     fun paint(
         canvas: Canvas,
         color: Color = Color.Unspecified,
@@ -281,7 +285,6 @@
      * currently set DrawStyle.
      * @param blendMode Blending algorithm to be applied to the Paragraph while painting.
      */
-    @ExperimentalTextApi
     fun paint(
         canvas: Canvas,
         color: Color = Color.Unspecified,
@@ -316,7 +319,6 @@
      * currently set DrawStyle.
      * @param blendMode Blending algorithm to be applied to the Paragraph while painting.
      */
-    @ExperimentalTextApi
     fun paint(
         canvas: Canvas,
         brush: Brush,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt
index f97de62..c16af63 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt
@@ -62,7 +62,7 @@
  * @see TextStyle
  */
 @Immutable
-class ParagraphStyle @ExperimentalTextApi constructor(
+class ParagraphStyle constructor(
     val textAlign: TextAlign? = null,
     val textDirection: TextDirection? = null,
     val lineHeight: TextUnit = TextUnit.Unspecified,
@@ -71,9 +71,6 @@
     val lineHeightStyle: LineHeightStyle? = null,
     val lineBreak: LineBreak? = null,
     val hyphens: Hyphens? = null,
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
-    @property:ExperimentalTextApi
     val textMotion: TextMotion? = null
 ) {
 
@@ -89,7 +86,6 @@
             "constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     constructor(
         textAlign: TextAlign? = null,
         textDirection: TextDirection? = null,
@@ -113,7 +109,6 @@
             "constructors.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     constructor(
         textAlign: TextAlign? = null,
         textDirection: TextDirection? = null,
@@ -133,35 +128,12 @@
         textMotion = null
     )
 
-    /**
-     * Paragraph styling configuration for a paragraph. The difference between [SpanStyle] and
-     * `ParagraphStyle` is that, `ParagraphStyle` can be applied to a whole [Paragraph] while
-     * [SpanStyle] can be applied at the character level.
-     * Once a portion of the text is marked with a `ParagraphStyle`, that portion will be separated from
-     * the remaining as if a line feed character was added.
-     *
-     * @sample androidx.compose.ui.text.samples.ParagraphStyleSample
-     * @sample androidx.compose.ui.text.samples.ParagraphStyleAnnotatedStringsSample
-     *
-     * @param textAlign The alignment of the text within the lines of the paragraph.
-     * @param textDirection The algorithm to be used to resolve the final text direction:
-     * Left To Right or Right To Left.
-     * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
-     * @param textIndent The indentation of the paragraph.
-     * @param platformStyle Platform specific [ParagraphStyle] parameters.
-     * @param lineHeightStyle the configuration for line height such as vertical alignment of the
-     * line, whether to apply additional space as a result of line height to top of first line top and
-     * bottom of last line. The configuration is applied only when a [lineHeight] is defined.
-     * When null, [LineHeightStyle.Default] is used.
-     * @param lineBreak The line breaking configuration for the text.
-     * @param hyphens The configuration of hyphenation.
-     *
-     * @see Paragraph
-     * @see AnnotatedString
-     * @see SpanStyle
-     * @see TextStyle
-     */
-    @OptIn(ExperimentalTextApi::class)
+    @Deprecated(
+        "ParagraphStyle constructors that do not take new stable parameters " +
+            "like LineBreak, Hyphens, TextMotion are deprecated. Please use the new stable " +
+            "constructors.",
+        level = DeprecationLevel.HIDDEN
+    )
     constructor(
         textAlign: TextAlign? = null,
         textDirection: TextDirection? = null,
@@ -198,7 +170,6 @@
      *
      * If the given paragraph style is null, returns this paragraph style.
      */
-    @OptIn(ExperimentalTextApi::class)
     @Stable
     fun merge(other: ParagraphStyle? = null): ParagraphStyle {
         if (other == null) return this
@@ -238,7 +209,6 @@
             "copy constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     fun copy(
         textAlign: TextAlign? = this.textAlign,
         textDirection: TextDirection? = this.textDirection,
@@ -264,7 +234,6 @@
             "copy constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     fun copy(
         textAlign: TextAlign? = this.textAlign,
         textDirection: TextDirection? = this.textDirection,
@@ -286,7 +255,12 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
+    @Deprecated(
+        "ParagraphStyle copy constructors that do not take new stable parameters " +
+            "like LineBreak, Hyphens, TextMotion are deprecated. Please use the new stable " +
+            "copy constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     fun copy(
         textAlign: TextAlign? = this.textAlign,
         textDirection: TextDirection? = this.textDirection,
@@ -310,7 +284,6 @@
         )
     }
 
-    @ExperimentalTextApi
     fun copy(
         textAlign: TextAlign? = this.textAlign,
         textDirection: TextDirection? = this.textDirection,
@@ -335,7 +308,6 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is ParagraphStyle) return false
@@ -353,7 +325,6 @@
         return true
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun hashCode(): Int {
         var result = textAlign?.hashCode() ?: 0
         result = 31 * result + (textDirection?.hashCode() ?: 0)
@@ -367,7 +338,6 @@
         return result
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun toString(): String {
         return "ParagraphStyle(" +
             "textAlign=$textAlign, " +
@@ -396,7 +366,6 @@
  * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
  * 1.0, so negative values and values greater than 1.0 are valid.
  */
-@OptIn(ExperimentalTextApi::class)
 @Stable
 fun lerp(start: ParagraphStyle, stop: ParagraphStyle, fraction: Float): ParagraphStyle {
     return ParagraphStyle(
@@ -435,7 +404,6 @@
     return lerp(startNonNull, stopNonNull, fraction)
 }
 
-@OptIn(ExperimentalTextApi::class)
 internal fun resolveParagraphStyleDefaults(
     style: ParagraphStyle,
     direction: LayoutDirection
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
index aafe77a..64056d4 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
@@ -101,9 +101,7 @@
     val textDecoration: TextDecoration? = null,
     val shadow: Shadow? = null,
     val platformStyle: PlatformSpanStyle? = null,
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @property:ExperimentalTextApi
-    @get:ExperimentalTextApi val drawStyle: DrawStyle? = null
+    val drawStyle: DrawStyle? = null
 ) {
 
     /**
@@ -138,6 +136,12 @@
      * @see TextStyle
      * @see ParagraphStyle
      */
+    @Deprecated(
+        "SpanStyle constructors that do not take new stable parameters " +
+            "like PlatformStyle, DrawStyle are deprecated. Please use the new stable " +
+            "constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -204,6 +208,12 @@
      * @see TextStyle
      * @see ParagraphStyle
      */
+    @Deprecated(
+        "SpanStyle constructors that do not take new stable parameters " +
+            "like PlatformStyle, DrawStyle are deprecated. Please use the new stable " +
+            "constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -273,7 +283,6 @@
      * @see TextStyle
      * @see ParagraphStyle
      */
-    @ExperimentalTextApi
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -349,7 +358,6 @@
      * @see TextStyle
      * @see ParagraphStyle
      */
-    @ExperimentalTextApi
     constructor(
         brush: Brush?,
         alpha: Float = Float.NaN,
@@ -395,18 +403,12 @@
     /**
      * Brush to draw text. If not null, overrides [color].
      */
-    @ExperimentalTextApi
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
     val brush: Brush? get() = this.textForegroundStyle.brush
 
     /**
      * Opacity of text. This value is either provided along side Brush, or via alpha channel in
      * color.
      */
-    @ExperimentalTextApi
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
     val alpha: Float get() = this.textForegroundStyle.alpha
 
     /**
@@ -418,7 +420,6 @@
      *
      * If the given span style is null, returns this span style.
      */
-    @OptIn(ExperimentalTextApi::class)
     @Stable
     fun merge(other: SpanStyle? = null): SpanStyle {
         if (other == null) return this
@@ -459,7 +460,12 @@
     @Stable
     operator fun plus(other: SpanStyle): SpanStyle = this.merge(other)
 
-    @OptIn(ExperimentalTextApi::class)
+    @Deprecated(
+        "SpanStyle copy constructors that do not take new stable parameters " +
+            "like PlatformStyle, DrawStyle are deprecated. Please use the new stable " +
+            "copy constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     fun copy(
         color: Color = this.color,
         fontSize: TextUnit = this.fontSize,
@@ -500,6 +506,12 @@
         )
     }
 
+    @Deprecated(
+        "SpanStyle copy constructors that do not take new stable parameters " +
+            "like PlatformStyle, DrawStyle are deprecated. Please use the new stable " +
+            "copy constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     fun copy(
         color: Color = this.color,
         fontSize: TextUnit = this.fontSize,
@@ -540,7 +552,6 @@
         )
     }
 
-    @ExperimentalTextApi
     fun copy(
         color: Color = this.color,
         fontSize: TextUnit = this.fontSize,
@@ -583,7 +594,6 @@
         )
     }
 
-    @ExperimentalTextApi
     fun copy(
         brush: Brush?,
         alpha: Float = this.alpha,
@@ -647,7 +657,6 @@
         return true
     }
 
-    @OptIn(ExperimentalTextApi::class)
     private fun hasSameNonLayoutAttributes(other: SpanStyle): Boolean {
         if (textForegroundStyle != other.textForegroundStyle) return false
         if (textDecoration != other.textDecoration) return false
@@ -656,7 +665,6 @@
         return true
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun hashCode(): Int {
         var result = color.hashCode()
         result = 31 * result + brush.hashCode()
@@ -695,7 +703,6 @@
         return result
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun toString(): String {
         return "SpanStyle(" +
             "color=$color, " +
@@ -748,7 +755,6 @@
  * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
  * 1.0, so negative values and values greater than 1.0 are valid.
  */
-@OptIn(ExperimentalTextApi::class)
 fun lerp(start: SpanStyle, stop: SpanStyle, fraction: Float): SpanStyle {
     return SpanStyle(
         textForegroundStyle = lerp(start.textForegroundStyle, stop.textForegroundStyle, fraction),
@@ -829,7 +835,6 @@
     return lerp(startNonNull, stopNonNull, fraction)
 }
 
-@OptIn(ExperimentalTextApi::class)
 internal fun resolveSpanStyleDefaults(style: SpanStyle) = SpanStyle(
     textForegroundStyle = style.textForegroundStyle.takeOrElse {
         TextForegroundStyle.from(DefaultColor)
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextPainter.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextPainter.kt
index 44c34a2..f9aa838 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextPainter.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextPainter.kt
@@ -40,8 +40,6 @@
 import kotlin.math.ceil
 import kotlin.math.roundToInt
 
-internal val DefaultTextBlendMode = BlendMode.SrcOver
-
 object TextPainter {
 
     // TODO(b/236964276): Deprecate when TextMeasurer and drawText are no longer Experimental
@@ -51,7 +49,6 @@
      * @param canvas a canvas to be drawn
      * @param textLayoutResult a result of text layout
      */
-    @OptIn(ExperimentalTextApi::class)
     fun paint(canvas: Canvas, textLayoutResult: TextLayoutResult) {
         val needClipping = textLayoutResult.hasVisualOverflow &&
             textLayoutResult.layoutInput.overflow != TextOverflow.Visible
@@ -143,7 +140,6 @@
  *
  * @see TextMeasurer
  */
-@ExperimentalTextApi
 fun DrawScope.drawText(
     textMeasurer: TextMeasurer,
     text: AnnotatedString,
@@ -211,7 +207,6 @@
  *
  * @see TextMeasurer
  */
-@ExperimentalTextApi
 fun DrawScope.drawText(
     textMeasurer: TextMeasurer,
     text: String,
@@ -263,7 +258,6 @@
  *
  * @sample androidx.compose.ui.text.samples.DrawTextLayoutResultSample
  */
-@ExperimentalTextApi
 fun DrawScope.drawText(
     textLayoutResult: TextLayoutResult,
     color: Color = Color.Unspecified,
@@ -326,7 +320,6 @@
  *
  * @sample androidx.compose.ui.text.samples.DrawTextLayoutResultSample
  */
-@ExperimentalTextApi
 fun DrawScope.drawText(
     textLayoutResult: TextLayoutResult,
     brush: Brush,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt
index ca8e2c9..1814b67 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt
@@ -78,7 +78,6 @@
             "constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -137,7 +136,6 @@
             "constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -229,6 +227,12 @@
      * @param lineBreak The line breaking configuration for the text.
      * @param hyphens The configuration of hyphenation.
      */
+    @Deprecated(
+        "TextStyle constructors that do not take new stable parameters " +
+            "like TextMotion are deprecated. Please use the new stable " +
+            "constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -323,7 +327,6 @@
      * @param hyphens The configuration of hyphenation.
      * @param textMotion Text character placement, whether to optimize for animated or static text.
      */
-    @ExperimentalTextApi
     constructor(
         color: Color = Color.Unspecified,
         fontSize: TextUnit = TextUnit.Unspecified,
@@ -425,7 +428,6 @@
      * @param hyphens The configuration of hyphenation.
      * @param textMotion Text character placement, whether to optimize for animated or static text.
      */
-    @ExperimentalTextApi
     constructor(
         brush: Brush?,
         alpha: Float = Float.NaN,
@@ -560,7 +562,6 @@
             "copy constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     fun copy(
         color: Color = this.spanStyle.color,
         fontSize: TextUnit = this.spanStyle.fontSize,
@@ -625,7 +626,6 @@
             "copy constructor.",
         level = DeprecationLevel.HIDDEN
     )
-    @OptIn(ExperimentalTextApi::class)
     fun copy(
         color: Color = this.spanStyle.color,
         fontSize: TextUnit = this.spanStyle.fontSize,
@@ -686,7 +686,12 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
+    @Deprecated(
+        "TextStyle copy constructors that do not take new stable parameters " +
+            "like LineBreak, Hyphens, and TextMotion are deprecated. Please use the new stable " +
+            "copy constructor.",
+        level = DeprecationLevel.HIDDEN
+    )
     fun copy(
         color: Color = this.spanStyle.color,
         fontSize: TextUnit = this.spanStyle.fontSize,
@@ -749,7 +754,6 @@
         )
     }
 
-    @ExperimentalTextApi
     fun copy(
         color: Color = this.spanStyle.color,
         fontSize: TextUnit = this.spanStyle.fontSize,
@@ -814,7 +818,6 @@
         )
     }
 
-    @ExperimentalTextApi
     fun copy(
         brush: Brush?,
         alpha: Float = this.spanStyle.alpha,
@@ -880,9 +883,6 @@
     /**
      * The brush to use when drawing text. If not null, overrides [color].
      */
-    @ExperimentalTextApi
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
     val brush: Brush? get() = this.spanStyle.brush
 
     /**
@@ -894,9 +894,6 @@
      * Opacity of text. This value is either provided along side Brush, or via alpha channel in
      * color.
      */
-    @ExperimentalTextApi
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
     val alpha: Float get() = this.spanStyle.alpha
 
     /**
@@ -972,9 +969,6 @@
     /**
      * Drawing style of text, whether fill in the text while drawing or stroke around the edges.
      */
-    @ExperimentalTextApi
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
     val drawStyle: DrawStyle? get() = this.spanStyle.drawStyle
 
     /**
@@ -1022,9 +1016,6 @@
     /**
      * Text character placement configuration, whether to optimize for animated or static text.
      */
-    @ExperimentalTextApi
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalTextApi
     val textMotion: TextMotion? get() = this.paragraphStyle.textMotion
 
     override fun equals(other: Any?): Boolean {
@@ -1070,7 +1061,6 @@
         return result
     }
 
-    @OptIn(ExperimentalTextApi::class)
     override fun toString(): String {
         return "TextStyle(" +
             "color=$color, " +
diff --git a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Paragraph.skiko.kt b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Paragraph.skiko.kt
index 7bbfe8d..83ba3cb 100644
--- a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Paragraph.skiko.kt
+++ b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Paragraph.skiko.kt
@@ -58,7 +58,6 @@
     actual fun getBoundingBox(offset: Int): Rect
     actual fun getWordBoundary(offset: Int): TextRange
     actual fun paint(canvas: Canvas, color: Color, shadow: Shadow?, textDecoration: TextDecoration?)
-    @ExperimentalTextApi
     actual fun paint(
         canvas: Canvas,
         color: Color,
@@ -67,7 +66,6 @@
         drawStyle: DrawStyle?,
         blendMode: BlendMode
     )
-    @ExperimentalTextApi
     actual fun paint(
         canvas: Canvas,
         brush: Brush,
diff --git a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/SkiaParagraph.skiko.kt b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/SkiaParagraph.skiko.kt
index 5ecc8b4..b91bd0f 100644
--- a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/SkiaParagraph.skiko.kt
+++ b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/SkiaParagraph.skiko.kt
@@ -310,7 +310,6 @@
         para.paint(canvas.nativeCanvas, 0.0f, 0.0f)
     }
 
-    @ExperimentalTextApi
     override fun paint(
         canvas: Canvas,
         color: Color,
@@ -332,7 +331,6 @@
     }
 
     // TODO(b/229518449): Implement this paint function that draws text with a Brush.
-    @ExperimentalTextApi
     override fun paint(
         canvas: Canvas,
         brush: Brush,
diff --git a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/style/TextMotion.skiko.kt b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/style/TextMotion.skiko.kt
index 67749c5..63c3537 100644
--- a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/style/TextMotion.skiko.kt
+++ b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/style/TextMotion.skiko.kt
@@ -17,10 +17,8 @@
 package androidx.compose.ui.text.style
 
 import androidx.compose.runtime.Immutable
-import androidx.compose.ui.text.ExperimentalTextApi
 
 @Immutable
-@ExperimentalTextApi
 actual class TextMotion private constructor() {
     actual companion object {
         actual val Static: TextMotion = TextMotion()
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt
index fa5f81c..3872a3b 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt
@@ -44,7 +44,6 @@
 
 @RunWith(JUnit4::class)
 class SpanStyleTest {
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with default values`() {
         val style = SpanStyle()
@@ -62,7 +61,6 @@
         assertThat(style.drawStyle).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized brush`() {
         val brush = Brush.linearGradient(colors = listOf(Color.Blue, Color.Red))
@@ -72,7 +70,6 @@
         assertThat(style.brush).isEqualTo(brush)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized brush and alpha`() {
         val brush = Brush.linearGradient(colors = listOf(Color.Blue, Color.Red))
@@ -83,7 +80,6 @@
         assertThat(style.alpha).isEqualTo(0.3f)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with gradient brush has unspecified color`() {
         val brush = Brush.linearGradient(colors = listOf(Color.Blue, Color.Red))
@@ -93,7 +89,6 @@
         assertThat(style.color).isEqualTo(Color.Unspecified)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with SolidColor converts to regular color`() {
         val brush = SolidColor(Color.Red)
@@ -112,7 +107,6 @@
         assertThat(style.color).isEqualTo(color)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with half-transparent color`() {
         val color = Color.Red.copy(alpha = 0.5f)
@@ -204,7 +198,6 @@
         assertThat(style.fontFamily).isEqualTo(fontFamily)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized drawStyle`() {
         val stroke = Stroke(width = 4f)
@@ -461,7 +454,6 @@
         assertThat(mergedStyle.platformStyle).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with brush has other brush and no color`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -475,7 +467,6 @@
         assertThat(mergedStyle.brush).isEqualTo(brush)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with unspecified brush has original brush`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -489,7 +480,6 @@
         assertThat(mergedStyle.brush).isEqualTo(brush)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge brush with brush uses other's alpha`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -504,7 +494,6 @@
         assertThat(mergedStyle.alpha).isEqualTo(0.6f)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge brush with brush uses current alpha if other's is NaN`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -519,7 +508,6 @@
         assertThat(mergedStyle.alpha).isEqualTo(0.3f)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with other's drawStyle is null should use this' drawStyle`() {
         val drawStyle1 = Stroke(cap = StrokeCap.Butt)
@@ -530,7 +518,6 @@
         assertThat(newSpanStyle.drawStyle).isEqualTo(drawStyle1)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with other's drawStyle is set should use other's drawStyle`() {
         val drawStyle1 = Stroke(cap = StrokeCap.Butt)
@@ -890,7 +877,6 @@
         assertThat(lerpedStyle.platformStyle).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp brush with a specified, b specified and t is smaller than half`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -903,7 +889,6 @@
         assertThat(newStyle.color).isEqualTo(Color.Unspecified)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp brush with a specified, b specified and t is larger than half`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -916,7 +901,6 @@
         assertThat(newStyle.color).isEqualTo(Color.Red)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp brush with a specified, b not specified and t is larger than half`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleLayoutAttributesTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleLayoutAttributesTest.kt
index a9c8a9f..d6376fd 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleLayoutAttributesTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleLayoutAttributesTest.kt
@@ -75,7 +75,6 @@
         ).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun returns_true_for_color_to_brush_change() {
         val style = TextStyle(color = Color.Red)
@@ -84,7 +83,6 @@
         ).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun returns_true_for_brush_to_color_change() {
         val style = TextStyle(brush = SolidColor(Color.Green))
@@ -93,7 +91,6 @@
         ).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun returns_true_for_brush_solid_color_change() {
         val style = TextStyle(brush = SolidColor(Color.Red))
@@ -103,7 +100,6 @@
         ).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun returns_true_for_brush_shader_change() {
         val style = TextStyle(brush = Brush.linearGradient(listOf(Color.Black, Color.White)))
@@ -114,7 +110,6 @@
         ).isTrue()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun returns_true_for_brush_alpha_change() {
         val brush = Brush.linearGradient(listOf(Color.Black, Color.White))
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleResolveDefaultsTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleResolveDefaultsTest.kt
index 5bff8e8..167bd68 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleResolveDefaultsTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleResolveDefaultsTest.kt
@@ -49,7 +49,6 @@
     private val DefaultLineHeight = TextUnit.Unspecified
     private val DefaultColor = Color.Black
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun test_default_values() {
         // We explicitly expect the default values since we do not want to change these values.
@@ -79,7 +78,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun test_use_provided_values_brush() {
         val brush = Brush.linearGradient(listOf(Color.White, Color.Black))
@@ -102,7 +100,6 @@
         ).isEqualTo(Hyphens.Auto)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun test_use_provided_values_shader_brush_color_unspecified() {
         val brush = Brush.linearGradient(listOf(Color.White, Color.Black))
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt
index c6cff1d..8886cf9 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt
@@ -56,7 +56,6 @@
 
 @RunWith(JUnit4::class)
 class TextStyleTest {
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with default values`() {
         val style = TextStyle()
@@ -85,7 +84,6 @@
         assertThat(style.lineBreak).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized brush`() {
         val brush = Brush.linearGradient(colors = listOf(Color.Blue, Color.Red))
@@ -95,7 +93,6 @@
         assertThat(style.brush).isEqualTo(brush)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized brush and alpha`() {
         val brush = Brush.linearGradient(colors = listOf(Color.Blue, Color.Red))
@@ -106,7 +103,6 @@
         assertThat(style.alpha).isEqualTo(0.3f)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with gradient brush has unspecified color`() {
         val brush = Brush.linearGradient(colors = listOf(Color.Blue, Color.Red))
@@ -116,7 +112,6 @@
         assertThat(style.color).isEqualTo(Color.Unspecified)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with SolidColor converts to regular color`() {
         val brush = SolidColor(Color.Red)
@@ -126,7 +121,6 @@
         assertThat(style.color).isEqualTo(Color.Red)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized textMotion`() {
         val style = TextStyle(textMotion = TextMotion.Animated)
@@ -134,7 +128,6 @@
         assertThat(style.textMotion).isEqualTo(TextMotion.Animated)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `empty copy with existing brush should not remove brush`() {
         val brush = Brush.linearGradient(listOf(Color.Red, Color.Blue))
@@ -151,7 +144,6 @@
         assertThat(style.copy().color).isEqualTo(Color.Red)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `empty copy with existing drawStyle should not remove drawStyle`() {
         val style = TextStyle(drawStyle = Stroke(2f))
@@ -160,7 +152,6 @@
     }
 
     @Suppress("DEPRECATION")
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `platformTextStyle copy with existing drawStyle should not remove drawStyle`() {
         val style = TextStyle(drawStyle = Stroke(2f))
@@ -170,7 +161,6 @@
         ).isEqualTo(Stroke(2f))
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `empty copy with existing hyphens should not remove hyphens`() {
         val style = TextStyle(hyphens = Hyphens.Auto)
@@ -185,7 +175,6 @@
         assertThat(style.copy(hyphens = Hyphens.None).hyphens).isEqualTo(Hyphens.None)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `brush copy with existing color should remove color`() {
         val style = TextStyle(color = Color.Red)
@@ -197,7 +186,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `color copy with existing brush should remove brush`() {
         val brush = Brush.linearGradient(listOf(Color.Red, Color.Blue))
@@ -209,7 +197,6 @@
         }
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `copy with textMotion returns new textMotion`() {
         val style = TextStyle(textMotion = TextMotion.Animated)
@@ -246,7 +233,6 @@
         assertThat(style.color).isEqualTo(color)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with half-transparent color`() {
         val color = Color.Red.copy(alpha = 0.5f)
@@ -365,7 +351,6 @@
         assertThat(style.lineBreak).isEqualTo(LineBreak.Heading)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `constructor with customized drawStyle`() {
         val stroke = Stroke(width = 8f)
@@ -593,7 +578,6 @@
         assertThat(newStyle.textDecoration).isEqualTo(otherStyle.textDecoration)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with other's drawStyle is null should use this' drawStyle`() {
         val drawStyle1 = Stroke(cap = StrokeCap.Butt)
@@ -604,7 +588,6 @@
         assertThat(newTextStyle.drawStyle).isEqualTo(drawStyle1)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with other's drawStyle is set should use other's drawStyle`() {
         val drawStyle1 = Stroke(cap = StrokeCap.Butt)
@@ -758,7 +741,6 @@
         assertThat(mergedStyle.platformStyle).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with brush has other brush and no color`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -772,7 +754,6 @@
         assertThat(mergedStyle.brush).isEqualTo(brush)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with unspecified brush has original brush`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -786,7 +767,6 @@
         assertThat(mergedStyle.brush).isEqualTo(brush)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge brush with brush uses other's alpha`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -801,7 +781,6 @@
         assertThat(mergedStyle.alpha).isEqualTo(0.6f)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge brush with brush uses current alpha if other's is NaN`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -856,7 +835,6 @@
         assertThat(mergedStyle.lineBreak).isEqualTo(otherStyle.lineBreak)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge null and non-null textMotion uses other's textMotion`() {
         val style = TextStyle(textMotion = null)
@@ -867,7 +845,6 @@
         assertThat(mergedStyle.textMotion).isEqualTo(otherStyle.textMotion)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge non-null and null textMotion uses original`() {
         val style = TextStyle(textMotion = TextMotion.Animated)
@@ -878,7 +855,6 @@
         assertThat(mergedStyle.textMotion).isEqualTo(style.textMotion)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with both null textMotion uses null`() {
         val style = TextStyle(textMotion = null)
@@ -889,7 +865,6 @@
         assertThat(mergedStyle.textMotion).isEqualTo(null)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `merge with both non-null textMotion uses other's textMotion`() {
         val style = TextStyle(textMotion = TextMotion.Animated)
@@ -1290,7 +1265,6 @@
         assertThat(newStyle.textDecoration).isEqualTo(decoration2)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp drawStyle with a and b are not null and fraction is smaller than half`() {
         val drawStyle1 = Fill
@@ -1304,7 +1278,6 @@
         assertThat(newStyle.drawStyle).isEqualTo(drawStyle1)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp drawStyle with a and b are not null and fraction is larger than half`() {
         val drawStyle1 = Fill
@@ -1453,7 +1426,6 @@
         assertThat(newStyle.platformStyle).isEqualTo(style.platformStyle)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp brush with a specified, b specified and t is smaller than half`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -1466,7 +1438,6 @@
         assertThat(newStyle.color).isEqualTo(Color.Unspecified)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp brush with a specified, b specified and t is larger than half`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -1479,7 +1450,6 @@
         assertThat(newStyle.color).isEqualTo(Color.Red)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp brush with a specified, b not specified and t is larger than half`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -1532,7 +1502,6 @@
         assertThat(lerpedStyle.lineBreak).isSameInstanceAs(otherStyle.lineBreak)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp with non-null start, null end, closer to start has non-null textMotion`() {
         val style = TextStyle(textMotion = TextMotion.Animated)
@@ -1543,7 +1512,6 @@
         assertThat(lerpedStyle.textMotion).isSameInstanceAs(style.textMotion)
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp with non-null start, null end, closer to end has null textMotion`() {
         val style = TextStyle(textMotion = TextMotion.Animated)
@@ -1554,7 +1522,6 @@
         assertThat(lerpedStyle.textMotion).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp with null start, non-null end, closer to start has null textMotion`() {
         val style = TextStyle(textMotion = null)
@@ -1565,7 +1532,6 @@
         assertThat(lerpedStyle.textMotion).isNull()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `lerp with null start, non-null end, closer to end has non-null textMotion`() {
         val style = TextStyle(textMotion = null)
@@ -1630,7 +1596,6 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `toSpanStyle return attributes with correct values for brush`() {
         val brush = Brush.linearGradient(listOf(Color.Blue, Color.Red))
@@ -1688,7 +1653,6 @@
         )
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun `toParagraphStyle return attributes with correct values`() {
         val textAlign = TextAlign.Justify
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 0e8e212..b03200b 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -149,7 +149,6 @@
     method public void onAttach();
     method public void onDetach();
     method public void onReset();
-    method public final void sideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
     property public final kotlinx.coroutines.CoroutineScope coroutineScope;
     property public final boolean isAttached;
     property public final androidx.compose.ui.Modifier.Node node;
@@ -1482,6 +1481,10 @@
     method public static androidx.compose.ui.Modifier nestedScroll(androidx.compose.ui.Modifier, androidx.compose.ui.input.nestedscroll.NestedScrollConnection connection, optional androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher? dispatcher);
   }
 
+  public final class NestedScrollNodeKt {
+    method public static androidx.compose.ui.node.DelegatableNode nestedScrollModifierNode(androidx.compose.ui.input.nestedscroll.NestedScrollConnection connection, androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher? dispatcher);
+  }
+
   @kotlin.jvm.JvmInline public final value class NestedScrollSource {
     field public static final androidx.compose.ui.input.nestedscroll.NestedScrollSource.Companion Companion;
   }
@@ -2226,7 +2229,7 @@
   }
 
   public interface ModifierLocalNode extends androidx.compose.ui.modifier.ModifierLocalReadScope androidx.compose.ui.node.DelegatableNode {
-    method public default <T> T! getCurrent(androidx.compose.ui.modifier.ModifierLocal<T>);
+    method public default <T> T getCurrent(androidx.compose.ui.modifier.ModifierLocal<T>);
     method public default androidx.compose.ui.modifier.ModifierLocalMap getProvidedValues();
     method public default <T> void provide(androidx.compose.ui.modifier.ModifierLocal<T> key, T value);
     property public default androidx.compose.ui.modifier.ModifierLocalMap providedValues;
@@ -2312,7 +2315,7 @@
 
   public final class LayoutModifierNodeKt {
     method public static void invalidateLayer(androidx.compose.ui.node.LayoutModifierNode);
-    method public static void invalidateMeasurements(androidx.compose.ui.node.LayoutModifierNode);
+    method public static void invalidateMeasurement(androidx.compose.ui.node.LayoutModifierNode);
     method public static void invalidatePlacement(androidx.compose.ui.node.LayoutModifierNode);
   }
 
@@ -2325,7 +2328,7 @@
     method public final Object? getValueOverride();
     method public abstract int hashCode();
     method public void inspectableProperties(androidx.compose.ui.platform.InspectorInfo);
-    method public abstract N update(N node);
+    method public abstract void update(N node);
     property public final kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> inspectableElements;
     property public final String? nameFallback;
     property public final Object? valueOverride;
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index faf1895..2520afc 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -159,7 +159,7 @@
     method public void onAttach();
     method public void onDetach();
     method public void onReset();
-    method public final void sideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
+    method @androidx.compose.ui.ExperimentalComposeUiApi public final void sideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
     property public final kotlinx.coroutines.CoroutineScope coroutineScope;
     property public final boolean isAttached;
     property public final androidx.compose.ui.Modifier.Node node;
@@ -1611,6 +1611,10 @@
     method public static androidx.compose.ui.Modifier nestedScroll(androidx.compose.ui.Modifier, androidx.compose.ui.input.nestedscroll.NestedScrollConnection connection, optional androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher? dispatcher);
   }
 
+  public final class NestedScrollNodeKt {
+    method public static androidx.compose.ui.node.DelegatableNode nestedScrollModifierNode(androidx.compose.ui.input.nestedscroll.NestedScrollConnection connection, androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher? dispatcher);
+  }
+
   @kotlin.jvm.JvmInline public final value class NestedScrollSource {
     field public static final androidx.compose.ui.input.nestedscroll.NestedScrollSource.Companion Companion;
   }
@@ -2436,7 +2440,7 @@
   }
 
   public interface ModifierLocalNode extends androidx.compose.ui.modifier.ModifierLocalReadScope androidx.compose.ui.node.DelegatableNode {
-    method public default <T> T! getCurrent(androidx.compose.ui.modifier.ModifierLocal<T>);
+    method public default <T> T getCurrent(androidx.compose.ui.modifier.ModifierLocal<T>);
     method public default androidx.compose.ui.modifier.ModifierLocalMap getProvidedValues();
     method public default <T> void provide(androidx.compose.ui.modifier.ModifierLocal<T> key, T value);
     property public default androidx.compose.ui.modifier.ModifierLocalMap providedValues;
@@ -2533,7 +2537,7 @@
 
   public final class LayoutModifierNodeKt {
     method public static void invalidateLayer(androidx.compose.ui.node.LayoutModifierNode);
-    method public static void invalidateMeasurements(androidx.compose.ui.node.LayoutModifierNode);
+    method public static void invalidateMeasurement(androidx.compose.ui.node.LayoutModifierNode);
     method public static void invalidatePlacement(androidx.compose.ui.node.LayoutModifierNode);
   }
 
@@ -2546,7 +2550,7 @@
     method public final Object? getValueOverride();
     method public abstract int hashCode();
     method public void inspectableProperties(androidx.compose.ui.platform.InspectorInfo);
-    method public abstract N update(N node);
+    method public abstract void update(N node);
     property public final kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> inspectableElements;
     property public final String? nameFallback;
     property public final Object? valueOverride;
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index c4c13ce..b449e04 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -149,7 +149,6 @@
     method public void onAttach();
     method public void onDetach();
     method public void onReset();
-    method public final void sideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
     property public final kotlinx.coroutines.CoroutineScope coroutineScope;
     property public final boolean isAttached;
     property public final androidx.compose.ui.Modifier.Node node;
@@ -1482,6 +1481,10 @@
     method public static androidx.compose.ui.Modifier nestedScroll(androidx.compose.ui.Modifier, androidx.compose.ui.input.nestedscroll.NestedScrollConnection connection, optional androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher? dispatcher);
   }
 
+  public final class NestedScrollNodeKt {
+    method public static androidx.compose.ui.node.DelegatableNode nestedScrollModifierNode(androidx.compose.ui.input.nestedscroll.NestedScrollConnection connection, androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher? dispatcher);
+  }
+
   @kotlin.jvm.JvmInline public final value class NestedScrollSource {
     field public static final androidx.compose.ui.input.nestedscroll.NestedScrollSource.Companion Companion;
   }
@@ -2233,7 +2236,7 @@
   }
 
   public interface ModifierLocalNode extends androidx.compose.ui.modifier.ModifierLocalReadScope androidx.compose.ui.node.DelegatableNode {
-    method public default <T> T! getCurrent(androidx.compose.ui.modifier.ModifierLocal<T>);
+    method public default <T> T getCurrent(androidx.compose.ui.modifier.ModifierLocal<T>);
     method public default androidx.compose.ui.modifier.ModifierLocalMap getProvidedValues();
     method public default <T> void provide(androidx.compose.ui.modifier.ModifierLocal<T> key, T value);
     property public default androidx.compose.ui.modifier.ModifierLocalMap providedValues;
@@ -2360,7 +2363,7 @@
 
   public final class LayoutModifierNodeKt {
     method public static void invalidateLayer(androidx.compose.ui.node.LayoutModifierNode);
-    method public static void invalidateMeasurements(androidx.compose.ui.node.LayoutModifierNode);
+    method public static void invalidateMeasurement(androidx.compose.ui.node.LayoutModifierNode);
     method public static void invalidatePlacement(androidx.compose.ui.node.LayoutModifierNode);
   }
 
@@ -2373,7 +2376,7 @@
     method public final Object? getValueOverride();
     method public abstract int hashCode();
     method public void inspectableProperties(androidx.compose.ui.platform.InspectorInfo);
-    method public abstract N update(N node);
+    method public abstract void update(N node);
     property public final kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> inspectableElements;
     property public final String? nameFallback;
     property public final Object? valueOverride;
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt
index 31c7afa..4335d1e 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt
@@ -143,9 +143,8 @@
     }
     data class CircleElement(val color: Color) : ModifierNodeElement<CircleNode>() {
         override fun create() = CircleNode(color)
-        override fun update(node: CircleNode): CircleNode {
+        override fun update(node: CircleNode) {
             node.color = color
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "color"
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/LayoutSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/LayoutSample.kt
index 7ef664a..6c41b9f8 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/LayoutSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/LayoutSample.kt
@@ -212,9 +212,8 @@
         val padding: Dp
     ) : ModifierNodeElement<VerticalPadding>() {
         override fun create() = VerticalPadding(padding)
-        override fun update(node: VerticalPadding): VerticalPadding {
+        override fun update(node: VerticalPadding) {
             node.padding = padding
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "verticalPadding"
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierCompositionLocalSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierCompositionLocalSample.kt
index df7fd7a..05eb8f0 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierCompositionLocalSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierCompositionLocalSample.kt
@@ -44,7 +44,7 @@
     }
     val BackgroundColorModifierElement = object : ModifierNodeElement<BackgroundColor>() {
         override fun create() = BackgroundColor()
-        override fun update(node: BackgroundColor) = node
+        override fun update(node: BackgroundColor) {}
         override fun hashCode() = System.identityHashCode(this)
         override fun equals(other: Any?) = (other === this)
         override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierSamples.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierSamples.kt
index 2d7bfb2..1039565 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierSamples.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/ModifierSamples.kt
@@ -323,9 +323,8 @@
         val color: Color
     ) : ModifierNodeElement<Circle>() {
         override fun create() = Circle(color)
-        override fun update(node: Circle): Circle {
+        override fun update(node: Circle) {
             node.color = color
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "circle"
@@ -350,9 +349,8 @@
     val HeadingElement = object : ModifierNodeElement<HeadingNode>() {
         override fun create() = HeadingNode()
 
-        override fun update(node: HeadingNode): HeadingNode {
+        override fun update(node: HeadingNode) {
             // Nothing to update.
-            return node
         }
 
         override fun InspectorInfo.inspectableProperties() {
@@ -391,9 +389,8 @@
         val callback: (PointerEvent) -> Unit
     ) : ModifierNodeElement<OnPointerEventNode>() {
         override fun create() = OnPointerEventNode(callback)
-        override fun update(node: OnPointerEventNode): OnPointerEventNode {
+        override fun update(node: OnPointerEventNode) {
             node.callback = callback
-            return node
         }
 
         override fun InspectorInfo.inspectableProperties() {
@@ -418,9 +415,8 @@
 
     data class LogSizeElement(val id: String) : ModifierNodeElement<SizeLoggerNode>() {
         override fun create(): SizeLoggerNode = SizeLoggerNode(id)
-        override fun update(node: SizeLoggerNode): SizeLoggerNode {
+        override fun update(node: SizeLoggerNode) {
             node.id = id
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "logSize"
@@ -452,9 +448,8 @@
 
     data class PositionLoggerElement(val id: String) : ModifierNodeElement<PositionLoggerNode>() {
         override fun create() = PositionLoggerNode(id)
-        override fun update(node: PositionLoggerNode): PositionLoggerNode {
+        override fun update(node: PositionLoggerNode) {
             node.id = id
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "logPosition"
@@ -481,9 +476,8 @@
         val logger: Logger
     ) : ModifierNodeElement<ProvideLoggerNode>() {
         override fun create() = ProvideLoggerNode(logger)
-        override fun update(node: ProvideLoggerNode): ProvideLoggerNode {
+        override fun update(node: ProvideLoggerNode) {
             node.provide(loggerLocal, logger)
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "provideLogger"
@@ -503,9 +497,8 @@
         val id: String
     ) : ModifierNodeElement<SizeLoggerNode>() {
         override fun create() = SizeLoggerNode(id)
-        override fun update(node: SizeLoggerNode): SizeLoggerNode {
+        override fun update(node: SizeLoggerNode) {
             node.id = id
-            return node
         }
         override fun InspectorInfo.inspectableProperties() {
             name = "logSize"
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
index afbe5df..df76fb54 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
@@ -286,8 +286,6 @@
         val switchRoleNode = toggleableNode.replacedChildren.last()
         val switchRoleNodeInfo = provider.createAccessibilityNodeInfo(switchRoleNode.id)!!
         assertEquals("android.view.View", switchRoleNodeInfo.className)
-// TODO(aelias)
-        // assertEquals("Switch", switchRoleNodeInfo.roleDescription)
 
         val stateDescription = when {
             Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/ParentDataModifierTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/ParentDataModifierTest.kt
index 8bc1531..adf79b7 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/ParentDataModifierTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/ParentDataModifierTest.kt
@@ -227,7 +227,9 @@
 private data class ParentDataAndLayoutElement(val data: String) :
     ModifierNodeElement<ParentDataAndLayoutNode>() {
     override fun create() = ParentDataAndLayoutNode(data)
-    override fun update(node: ParentDataAndLayoutNode) = node.also { it.data = data }
+    override fun update(node: ParentDataAndLayoutNode) {
+        node.data = data
+    }
 }
 
 class ParentDataAndLayoutNode(var data: String) : Modifier.Node(), LayoutModifierNode,
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CombinedFocusModifierNodeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CombinedFocusModifierNodeTest.kt
index 7a42a32..9e53f72 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CombinedFocusModifierNodeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CombinedFocusModifierNodeTest.kt
@@ -200,8 +200,8 @@
         val combinedFocusNode: CombinedFocusNode
     ) : ModifierNodeElement<CombinedFocusNode>() {
         override fun create(): CombinedFocusNode = combinedFocusNode
-        override fun update(node: CombinedFocusNode) = node.apply {
-            focusState = combinedFocusNode.focusState
+        override fun update(node: CombinedFocusNode) {
+            node.focusState = combinedFocusNode.focusState
         }
     }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
index 37234ac..4f8d561 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
@@ -830,7 +830,7 @@
     }
 
     override fun create() = instance
-    override fun update(node: Modifier.Node) = node
+    override fun update(node: Modifier.Node) {}
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is SuspendPointerInputModifierNodeElement) return false
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/ResizingComposeViewTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/ResizingComposeViewTest.kt
index eaed850..1171a38 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/ResizingComposeViewTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/ResizingComposeViewTest.kt
@@ -396,8 +396,8 @@
     override fun create() = RemeasurementModifierNode().also {
         onRemeasurementAvailable(it)
     }
-    override fun update(node: RemeasurementModifierNode) = node.also {
-        onRemeasurementAvailable(it)
+    override fun update(node: RemeasurementModifierNode) {
+        onRemeasurementAvailable(node)
     }
     override fun hashCode(): Int = 242
     override fun equals(other: Any?) = other === this
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/CompositionLocalMapInjectionTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/CompositionLocalMapInjectionTest.kt
index 3526180..a38a249 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/CompositionLocalMapInjectionTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/CompositionLocalMapInjectionTest.kt
@@ -229,7 +229,7 @@
         override fun create() = fn()
         override fun hashCode() = System.identityHashCode(this)
         override fun equals(other: Any?) = other === this
-        override fun update(node: T) = node
+        override fun update(node: T) {}
     }
 
 class ConsumeInDrawNode : CompositionLocalConsumerModifierNode, DrawModifierNode, Modifier.Node() {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/ModifierNodeReuseAndDeactivationTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/ModifierNodeReuseAndDeactivationTest.kt
index 9748b17..1c7d152 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/ModifierNodeReuseAndDeactivationTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/modifier/ModifierNodeReuseAndDeactivationTest.kt
@@ -246,7 +246,7 @@
             override fun create(): Modifier.Node = nodeInstance
             override fun hashCode(): Int = System.identityHashCode(this)
             override fun equals(other: Any?) = (other === this)
-            override fun update(node: Modifier.Node) = nodeInstance
+            override fun update(node: Modifier.Node) { }
         }
 
         var active by mutableStateOf(true)
@@ -909,7 +909,7 @@
             }
         }
 
-        override fun update(node: Modifier.Node) = node.apply { onUpdate() }
+        override fun update(node: Modifier.Node) { onUpdate() }
 
         override fun hashCode(): Int = "ModifierNodeReuseAndDeactivationTest".hashCode()
 
@@ -929,9 +929,9 @@
 ) : ModifierNodeElement<StatelessModifierElement.Node>() {
     override fun create() = Node(size, onInvalidate)
 
-    override fun update(node: Node) = node.also {
-        it.size = size
-        it.onMeasure = onInvalidate
+    override fun update(node: Node) {
+        node.size = size
+        node.onMeasure = onInvalidate
     }
 
     class Node(var size: Int, var onMeasure: () -> Unit) : Modifier.Node(), LayoutModifierNode {
@@ -953,8 +953,8 @@
 ) : ModifierNodeElement<DelegatingModifierElement.Node>() {
     override fun create() = Node(onDelegatedNodeReset)
 
-    override fun update(node: Node) = node.also {
-        it.onReset = onDelegatedNodeReset
+    override fun update(node: Node) {
+        node.onReset = onDelegatedNodeReset
     }
 
     class Node(var onReset: () -> Unit) : DelegatingNode() {
@@ -973,8 +973,8 @@
 ) : ModifierNodeElement<LayerModifierElement.Node>() {
     override fun create() = Node(layerBlock)
 
-    override fun update(node: Node) = node.also {
-        it.layerBlock = layerBlock
+    override fun update(node: Node) {
+        node.layerBlock = layerBlock
     }
 
     class Node(var layerBlock: () -> Unit) : Modifier.Node(), LayoutModifierNode {
@@ -997,8 +997,8 @@
 ) : ModifierNodeElement<ObserverModifierElement.Node>() {
     override fun create() = Node(observedBlock)
 
-    override fun update(node: Node) = node.also {
-        it.observedBlock = observedBlock
+    override fun update(node: Node) {
+        node.observedBlock = observedBlock
     }
 
     class Node(var observedBlock: () -> Unit) : Modifier.Node(), ObserverNode {
@@ -1024,8 +1024,8 @@
 ) : ModifierNodeElement<LayoutModifierElement.Node>() {
     override fun create() = Node(measureBlock)
 
-    override fun update(node: Node) = node.also {
-        it.measureBlock = measureBlock
+    override fun update(node: Node) {
+        node.measureBlock = measureBlock
     }
 
     class Node(var measureBlock: () -> Unit) : Modifier.Node(), LayoutModifierNode {
@@ -1062,8 +1062,8 @@
 ) : ModifierNodeElement<DrawModifierElement.Node>() {
     override fun create() = Node(drawBlock)
 
-    override fun update(node: Node) = node.also {
-        it.drawBlock = drawBlock
+    override fun update(node: Node) {
+        node.drawBlock = drawBlock
     }
 
     class Node(var drawBlock: () -> Unit) : Modifier.Node(), DrawModifierNode {
@@ -1084,7 +1084,7 @@
 
 private object StatelessLayoutElement1 : ModifierNodeElement<StatelessLayoutModifier1>() {
     override fun create() = StatelessLayoutModifier1()
-    override fun update(node: StatelessLayoutModifier1) = node
+    override fun update(node: StatelessLayoutModifier1) {}
     override fun hashCode(): Int = 241
     override fun equals(other: Any?) = other === this
 }
@@ -1103,7 +1103,7 @@
 
 private object StatelessLayoutElement2 : ModifierNodeElement<StatelessLayoutModifier2>() {
     override fun create() = StatelessLayoutModifier2()
-    override fun update(node: StatelessLayoutModifier2) = node
+    override fun update(node: StatelessLayoutModifier2) {}
     override fun hashCode(): Int = 242
     override fun equals(other: Any?) = other === this
 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalConsumerModifierNodeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalConsumerModifierNodeTest.kt
index 8fa9d75..451605f 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalConsumerModifierNodeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalConsumerModifierNodeTest.kt
@@ -304,7 +304,7 @@
         crossinline create: () -> T
     ): ModifierNodeElement<T> = object : ModifierNodeElement<T>() {
         override fun create(): T = create()
-        override fun update(node: T) = node
+        override fun update(node: T) {}
         override fun hashCode(): Int = System.identityHashCode(this)
         override fun equals(other: Any?) = (other === this)
     }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/DelegatableNodeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/DelegatableNodeTest.kt
index e3d113b..fe89fe6 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/DelegatableNodeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/DelegatableNodeTest.kt
@@ -593,7 +593,7 @@
         val factory: () -> T
     ) : ModifierNodeElement<T>() {
         override fun create(): T = factory()
-        override fun update(node: T) = node
+        override fun update(node: T) {}
         override fun InspectorInfo.inspectableProperties() {
             name = "testNode"
         }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/InvalidateSubtreeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/InvalidateSubtreeTest.kt
index ad0f352..2e3d335 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/InvalidateSubtreeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/InvalidateSubtreeTest.kt
@@ -152,7 +152,7 @@
         override fun create() = object : Modifier.Node() {}
             .apply<Modifier.Node>(onCreate)
 
-        override fun update(node: Modifier.Node) = node
+        override fun update(node: Modifier.Node) {}
 
         override fun InspectorInfo.inspectableProperties() {
             name = "Invalidate Subtree Modifier.Node"
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ModifierNodeCoroutineScopeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ModifierNodeCoroutineScopeTest.kt
index 625885d..2c3e809 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ModifierNodeCoroutineScopeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ModifierNodeCoroutineScopeTest.kt
@@ -58,7 +58,7 @@
 
         val testElement = object : ModifierNodeElement<TestNode>() {
             override fun create(): TestNode = TestNode()
-            override fun update(node: TestNode): TestNode = node
+            override fun update(node: TestNode) {}
 
             override fun hashCode(): Int = 0
             override fun equals(other: Any?): Boolean = other === this
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
index 29cafc1..a875d116 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
@@ -253,7 +253,7 @@
     val node: T
 ) : ModifierNodeElement<T>() {
     override fun create(): T = node
-    override fun update(node: T): T = this.node
+    override fun update(node: T) {}
     override fun InspectorInfo.inspectableProperties() {
         name = modifierName
     }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ObserverNodeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ObserverNodeTest.kt
index 1049aaf..620cc57 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ObserverNodeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/ObserverNodeTest.kt
@@ -170,7 +170,7 @@
         val node: T
     ) : ModifierNodeElement<T>() {
         override fun create(): T = node
-        override fun update(node: T) = this.node
+        override fun update(node: T) {}
         override fun InspectorInfo.inspectableProperties() {
             name = "testNode"
         }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
index 10bf2e4..bdbd7fc 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
@@ -1060,5 +1060,5 @@
 
 internal data class NodeElement(val node: Modifier.Node) : ModifierNodeElement<Modifier.Node>() {
     override fun create(): Modifier.Node = node
-    override fun update(node: Modifier.Node): Modifier.Node = node
+    override fun update(node: Modifier.Node) {}
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt
index a1872aa..cf111e5 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt
@@ -304,7 +304,7 @@
     val map: CompositionLocalMap
 ) : ModifierNodeElement<CompositionLocalMapInjectionNode>() {
     override fun create() = CompositionLocalMapInjectionNode(map)
-    override fun update(node: CompositionLocalMapInjectionNode) = node.also { it.map = map }
+    override fun update(node: CompositionLocalMapInjectionNode) { node.map = map }
     override fun hashCode(): Int = map.hashCode()
     override fun equals(other: Any?): Boolean {
         return other is CompositionLocalMapInjectionElement && other.map == map
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt
index eb96674..919acfe 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt
@@ -246,7 +246,6 @@
             check(coordinator != null)
             isAttached = true
             onAttach()
-            // TODO(lmr): run side effects?
         }
 
         internal open fun detach() {
@@ -306,6 +305,7 @@
          *
          * This API can only be called if the node [isAttached].
          */
+        @ExperimentalComposeUiApi
         fun sideEffect(effect: () -> Unit) {
             requireOwner().registerOnEndApplyChangesListener(effect)
         }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ZIndexModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ZIndexModifier.kt
index d44f338..30f3372 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ZIndexModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ZIndexModifier.kt
@@ -42,8 +42,8 @@
 
 internal data class ZIndexElement(val zIndex: Float) : ModifierNodeElement<ZIndexModifier>() {
     override fun create() = ZIndexModifier(zIndex)
-    override fun update(node: ZIndexModifier) = node.also {
-        it.zIndex = zIndex
+    override fun update(node: ZIndexModifier) {
+        node.zIndex = zIndex
     }
     override fun InspectorInfo.inspectableProperties() {
         name = "zIndex"
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt
index ef755f7..aecd204 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt
@@ -100,8 +100,8 @@
 ) : ModifierNodeElement<DrawBackgroundModifier>() {
     override fun create() = DrawBackgroundModifier(onDraw)
 
-    override fun update(node: DrawBackgroundModifier) = node.apply {
-        onDraw = [email protected]
+    override fun update(node: DrawBackgroundModifier) {
+        node.onDraw = onDraw
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -148,8 +148,8 @@
         return CacheDrawNode(CacheDrawScope(), onBuildDrawCache)
     }
 
-    override fun update(node: CacheDrawNode) = node.apply {
-        block = onBuildDrawCache
+    override fun update(node: CacheDrawNode) {
+        node.block = onBuildDrawCache
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -281,8 +281,8 @@
 ) : ModifierNodeElement<DrawWithContentModifier>() {
     override fun create() = DrawWithContentModifier(onDraw)
 
-    override fun update(node: DrawWithContentModifier) = node.apply {
-        onDraw = [email protected]
+    override fun update(node: DrawWithContentModifier) {
+        node.onDraw = onDraw
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/PainterModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/PainterModifier.kt
index d41b0b9..a62e2c3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/PainterModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/PainterModifier.kt
@@ -38,7 +38,7 @@
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.node.invalidateDraw
 import androidx.compose.ui.node.invalidateLayer
-import androidx.compose.ui.node.invalidateMeasurements
+import androidx.compose.ui.node.invalidateMeasurement
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.IntSize
@@ -106,7 +106,7 @@
         )
     }
 
-    override fun update(node: PainterModifierNode): PainterModifierNode {
+    override fun update(node: PainterModifierNode) {
         val intrinsicsChanged = node.sizeToIntrinsics != sizeToIntrinsics ||
             (sizeToIntrinsics && node.painter.intrinsicSize != painter.intrinsicSize)
 
@@ -119,12 +119,10 @@
 
         // Only remeasure if intrinsics have changed.
         if (intrinsicsChanged) {
-            node.invalidateMeasurements()
+            node.invalidateMeasurement()
         }
         // redraw because one of the node properties has changed.
         node.invalidateDraw()
-
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt
index 1dd3153..5719fe3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt
@@ -39,8 +39,8 @@
 ) : ModifierNodeElement<FocusChangedModifierNode>() {
     override fun create() = FocusChangedModifierNode(onFocusChanged)
 
-    override fun update(node: FocusChangedModifierNode) = node.apply {
-        onFocusChanged = [email protected]
+    override fun update(node: FocusChangedModifierNode) {
+        node.onFocusChanged = onFocusChanged
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusEventModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusEventModifier.kt
index f38261a..f0bc4aa 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusEventModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusEventModifier.kt
@@ -46,8 +46,8 @@
 ) : ModifierNodeElement<FocusEventModifierNodeImpl>() {
     override fun create() = FocusEventModifierNodeImpl(onFocusEvent)
 
-    override fun update(node: FocusEventModifierNodeImpl) = node.apply {
-        onFocusEvent = [email protected]
+    override fun update(node: FocusEventModifierNodeImpl) {
+        node.onFocusEvent = onFocusEvent
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
index 35f5332..6f5912d 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
@@ -65,7 +65,7 @@
     override val modifier: Modifier = object : ModifierNodeElement<FocusTargetModifierNode>() {
         override fun create() = rootFocusNode
 
-        override fun update(node: FocusTargetModifierNode) = node
+        override fun update(node: FocusTargetModifierNode) {}
 
         override fun InspectorInfo.inspectableProperties() {
             name = "RootFocusTarget"
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusProperties.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusProperties.kt
index 8404c04..d9acf72 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusProperties.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusProperties.kt
@@ -187,8 +187,8 @@
 ) : ModifierNodeElement<FocusPropertiesModifierNodeImpl>() {
     override fun create() = FocusPropertiesModifierNodeImpl(scope)
 
-    override fun update(node: FocusPropertiesModifierNodeImpl) = node.apply {
-        focusPropertiesScope = scope
+    override fun update(node: FocusPropertiesModifierNodeImpl) {
+        node.focusPropertiesScope = scope
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt
index dd6fd9f..c8ab894 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt
@@ -55,10 +55,10 @@
 ) : ModifierNodeElement<FocusRequesterModifierNodeImpl>() {
     override fun create() = FocusRequesterModifierNodeImpl(focusRequester)
 
-    override fun update(node: FocusRequesterModifierNodeImpl) = node.apply {
-        focusRequester.focusRequesterNodes -= this
-        focusRequester = [email protected]
-        focusRequester.focusRequesterNodes += this
+    override fun update(node: FocusRequesterModifierNodeImpl) {
+        node.focusRequester.focusRequesterNodes -= node
+        node.focusRequester = focusRequester
+        node.focusRequester.focusRequesterNodes += node
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetModifierNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetModifierNode.kt
index f09430b..456b959 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetModifierNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetModifierNode.kt
@@ -188,7 +188,7 @@
     internal object FocusTargetModifierElement : ModifierNodeElement<FocusTargetModifierNode>() {
         override fun create() = FocusTargetModifierNode()
 
-        override fun update(node: FocusTargetModifierNode) = node
+        override fun update(node: FocusTargetModifierNode) {}
 
         override fun InspectorInfo.inspectableProperties() {
             name = "focusTarget"
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt
index 3f5ac4b..267b71f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt
@@ -421,7 +421,7 @@
         )
     }
 
-    override fun update(node: SimpleGraphicsLayerModifier): SimpleGraphicsLayerModifier {
+    override fun update(node: SimpleGraphicsLayerModifier) {
         node.scaleX = scaleX
         node.scaleY = scaleY
         node.alpha = alpha
@@ -440,8 +440,6 @@
         node.spotShadowColor = spotShadowColor
         node.compositingStrategy = compositingStrategy
         node.invalidateLayerBlock()
-
-        return node
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -545,9 +543,9 @@
 ) : ModifierNodeElement<BlockGraphicsLayerModifier>() {
     override fun create() = BlockGraphicsLayerModifier(block)
 
-    override fun update(node: BlockGraphicsLayerModifier) = node.apply {
-        layerBlock = block
-        invalidateLayerBlock()
+    override fun update(node: BlockGraphicsLayerModifier) {
+        node.layerBlock = block
+        node.invalidateLayerBlock()
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt
index b823385..3d26c05 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt
@@ -56,9 +56,9 @@
 ) : ModifierNodeElement<KeyInputModifierNodeImpl>() {
     override fun create() = KeyInputModifierNodeImpl(onKeyEvent, onPreKeyEvent)
 
-    override fun update(node: KeyInputModifierNodeImpl) = node.apply {
-        onEvent = onKeyEvent
-        onPreEvent = onPreKeyEvent
+    override fun update(node: KeyInputModifierNodeImpl) {
+        node.onEvent = onKeyEvent
+        node.onPreEvent = onPreKeyEvent
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/SoftwareKeyboardInterceptionModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/SoftwareKeyboardInterceptionModifier.kt
index 88fc93a..be03189 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/SoftwareKeyboardInterceptionModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/SoftwareKeyboardInterceptionModifier.kt
@@ -72,9 +72,9 @@
         onPreEvent = onPreKeyEvent
     )
 
-    override fun update(node: InterceptedKeyInputModifierNodeImpl) = node.apply {
-        onEvent = onKeyEvent
-        onPreEvent = onPreKeyEvent
+    override fun update(node: InterceptedKeyInputModifierNodeImpl) {
+        node.onEvent = onKeyEvent
+        node.onPreEvent = onPreKeyEvent
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollModifier.kt
index 1bf2e8c..2d61ab5 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollModifier.kt
@@ -342,10 +342,8 @@
         return NestedScrollNode(connection, dispatcher)
     }
 
-    override fun update(node: NestedScrollNode): NestedScrollNode {
-        node.connection = connection
-        node.updateDispatcher(dispatcher)
-        return node
+    override fun update(node: NestedScrollNode) {
+        node.updateNode(connection, dispatcher)
     }
 
     override fun hashCode(): Int {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollNode.kt
index 093b26d..f1282fb 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/nestedscroll/NestedScrollNode.kt
@@ -16,24 +16,37 @@
 
 package androidx.compose.ui.input.nestedscroll
 
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.modifier.ModifierLocalMap
 import androidx.compose.ui.modifier.ModifierLocalNode
 import androidx.compose.ui.modifier.modifierLocalMapOf
 import androidx.compose.ui.modifier.modifierLocalOf
-import androidx.compose.ui.node.DelegatingNode
+import androidx.compose.ui.node.DelegatableNode
 import androidx.compose.ui.unit.Velocity
 import kotlinx.coroutines.CoroutineScope
 
 internal val ModifierLocalNestedScroll = modifierLocalOf<NestedScrollNode?> { null }
 
 /**
+ * This creates a Nested Scroll Modifier node that can be delegated to. In most case you should
+ * use [Modifier.nestedScroll] since that implementation also uses this. Use this factory to create
+ * nodes that can be delegated to.
+ */
+fun nestedScrollModifierNode(
+    connection: NestedScrollConnection,
+    dispatcher: NestedScrollDispatcher?
+): DelegatableNode {
+    return NestedScrollNode(connection, dispatcher)
+}
+
+/**
  * NestedScroll using ModifierLocal as implementation.
  */
 internal class NestedScrollNode(
     var connection: NestedScrollConnection,
     dispatcher: NestedScrollDispatcher?
-) : ModifierLocalNode, NestedScrollConnection, DelegatingNode() {
+) : ModifierLocalNode, NestedScrollConnection, DelegatableNode, Modifier.Node() {
 
     // Resolved dispatcher for re-use in case of null dispatcher is passed.
     private var resolvedDispatcher: NestedScrollDispatcher
@@ -46,7 +59,7 @@
         get() = if (isAttached) ModifierLocalNestedScroll.current else null
 
     private val parentConnection: NestedScrollConnection?
-        get() = ModifierLocalNestedScroll.current
+        get() = if (isAttached) ModifierLocalNestedScroll.current else null
 
     override val providedValues: ModifierLocalMap
         get() = modifierLocalMapOf(ModifierLocalNestedScroll to this)
@@ -99,7 +112,7 @@
     }
 
     // On receiving a new dispatcher, re-setting fields
-    fun updateDispatcher(newDispatcher: NestedScrollDispatcher?) {
+    private fun updateDispatcher(newDispatcher: NestedScrollDispatcher?) {
         resetDispatcherFields() // Reset fields of current dispatcher.
 
         // Update dispatcher associated with this node.
@@ -139,4 +152,12 @@
     private fun resetDispatcherFields() {
         resolvedDispatcher.modifierLocalNode = null
     }
+
+    internal fun updateNode(
+        connection: NestedScrollConnection,
+        dispatcher: NestedScrollDispatcher?
+    ) {
+        this.connection = connection
+        updateDispatcher(dispatcher)
+    }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt
index 3df0795..3685a4c 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt
@@ -319,10 +319,8 @@
         return SuspendingPointerInputModifierNodeImpl(pointerInputHandler)
     }
 
-    override fun update(node: SuspendingPointerInputModifierNodeImpl):
-        SuspendingPointerInputModifierNodeImpl {
+    override fun update(node: SuspendingPointerInputModifierNodeImpl) {
         node.pointerInputHandler = pointerInputHandler
-        return node
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryInputModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryInputModifier.kt
index 6b2351c..9b5bd47 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryInputModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryInputModifier.kt
@@ -83,9 +83,9 @@
         onPreEvent = onPreRotaryScrollEvent
     )
 
-    override fun update(node: RotaryInputModifierNodeImpl) = node.apply {
-        onEvent = onRotaryScrollEvent
-        onPreEvent = onPreRotaryScrollEvent
+    override fun update(node: RotaryInputModifierNodeImpl) {
+        node.onEvent = onRotaryScrollEvent
+        node.onPreEvent = onPreRotaryScrollEvent
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutId.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutId.kt
index 7c3e9d3..c73c968 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutId.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutId.kt
@@ -37,8 +37,8 @@
 ) : ModifierNodeElement<LayoutIdModifier>() {
     override fun create() = LayoutIdModifier(layoutId)
 
-    override fun update(node: LayoutIdModifier): LayoutIdModifier = node.also {
-        it.layoutId = layoutId
+    override fun update(node: LayoutIdModifier) {
+        node.layoutId = layoutId
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutModifier.kt
index e9f36f0..d96e68e 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutModifier.kt
@@ -274,8 +274,8 @@
 ) : ModifierNodeElement<LayoutModifierImpl>() {
     override fun create() = LayoutModifierImpl(measure)
 
-    override fun update(node: LayoutModifierImpl) = node.apply {
-        measureBlock = measure
+    override fun update(node: LayoutModifierImpl) {
+        node.measureBlock = measure
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LookaheadScope.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LookaheadScope.kt
index 298b719..ccdd77b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LookaheadScope.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LookaheadScope.kt
@@ -156,8 +156,9 @@
     ) -> MeasureResult,
 ) : ModifierNodeElement<IntermediateLayoutModifierNode>() {
     override fun create() = IntermediateLayoutModifierNode(measure)
-    override fun update(node: IntermediateLayoutModifierNode): IntermediateLayoutModifierNode =
-        node.apply { this.measureBlock = measure }
+    override fun update(node: IntermediateLayoutModifierNode) {
+        node.measureBlock = measure
+    }
 
     override fun InspectorInfo.inspectableProperties() {
         name = "intermediateLayout"
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnGloballyPositionedModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnGloballyPositionedModifier.kt
index 96790aa..d6ee7f8 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnGloballyPositionedModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnGloballyPositionedModifier.kt
@@ -61,10 +61,9 @@
         return onGloballyPositioned.hashCode()
     }
 
-    override fun update(node: OnGloballyPositionedNode): OnGloballyPositionedNode =
-        node.also {
-            it.callback = onGloballyPositioned
-        }
+    override fun update(node: OnGloballyPositionedNode) {
+        node.callback = onGloballyPositioned
+    }
 
     override fun InspectorInfo.inspectableProperties() {
         name = "onGloballyPositioned"
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnPlacedModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnPlacedModifier.kt
index 909f5ab..c4acf63 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnPlacedModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnPlacedModifier.kt
@@ -40,8 +40,8 @@
 ) : ModifierNodeElement<OnPlacedNode>() {
     override fun create() = OnPlacedNode(callback = onPlaced)
 
-    override fun update(node: OnPlacedNode) = node.apply {
-        callback = onPlaced
+    override fun update(node: OnPlacedNode) {
+        node.callback = onPlaced
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutModifierNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutModifierNode.kt
index c1b1344..b8146be 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutModifierNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutModifierNode.kt
@@ -151,7 +151,7 @@
  * This invalidates the current node's measure result, and ensures that a remeasurement
  * (the measurement block rerun) of this node will happen for the next frame.
  */
-fun LayoutModifierNode.invalidateMeasurements() = requireLayoutNode().invalidateMeasurements()
+fun LayoutModifierNode.invalidateMeasurement() = requireLayoutNode().invalidateMeasurements()
 
 internal fun LayoutModifierNode.requestRemeasure() = requireLayoutNode().requestRemeasure()
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierNodeElement.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierNodeElement.kt
index 0e163c2..0bbb386 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierNodeElement.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierNodeElement.kt
@@ -67,7 +67,7 @@
      * application. This function will have the current node instance passed in as a parameter, and
      * it is expected that the node will be brought up to date.
      */
-    abstract fun update(node: N): N
+    abstract fun update(node: N)
 
     /**
      * Populates an [InspectorInfo] object with attributes to display in the layout inspector. This
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
index aa342c6..2b2847f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
@@ -127,7 +127,7 @@
                         // this is "the same" modifier, but some things have changed so we want to
                         // reuse the node but also update it
                         val beforeUpdate = node
-                        node = updateNodeAndReplaceIfNeeded(prev, next, beforeUpdate)
+                        node = updateNode(prev, next, beforeUpdate)
                         logger?.nodeUpdated(i, i, prev, next, beforeUpdate, node)
                     }
                     ActionReuse -> {
@@ -395,7 +395,7 @@
             val next = after[newIndex]
             if (prev != next) {
                 val beforeUpdate = node
-                node = updateNodeAndReplaceIfNeeded(prev, next, beforeUpdate)
+                node = updateNode(prev, next, beforeUpdate)
                 logger?.nodeUpdated(oldIndex, newIndex, prev, next, beforeUpdate, node)
             } else {
                 logger?.nodeReused(oldIndex, newIndex, prev, next, node)
@@ -573,35 +573,23 @@
         return node
     }
 
-    private fun updateNodeAndReplaceIfNeeded(
+    private fun updateNode(
         prev: Modifier.Element,
         next: Modifier.Element,
         node: Modifier.Node
     ): Modifier.Node {
         when {
             prev is ModifierNodeElement<*> && next is ModifierNodeElement<*> -> {
-                val updated = next.updateUnsafe(node)
-                if (updated !== node) {
-                    check(!updated.isAttached)
-                    updated.insertedNodeAwaitingAttachForInvalidation = true
-                    // if a new instance is returned, we want to detach the old one
-                    if (node.isAttached) {
-                        autoInvalidateRemovedNode(node)
-                        node.detach()
-                    }
-                    return replaceNode(node, updated)
+                next.updateUnsafe(node)
+                if (node.isAttached) {
+                    // the modifier element is labeled as "auto invalidate", which means
+                    // that since the node was updated, we need to invalidate everything
+                    // relevant to it.
+                    autoInvalidateUpdatedNode(node)
                 } else {
-                    // the node was updated. we are done.
-                    if (updated.isAttached) {
-                        // the modifier element is labeled as "auto invalidate", which means
-                        // that since the node was updated, we need to invalidate everything
-                        // relevant to it.
-                        autoInvalidateUpdatedNode(updated)
-                    } else {
-                        updated.updatedNodeAwaitingAttachForInvalidation = true
-                    }
-                    return updated
+                    node.updatedNodeAwaitingAttachForInvalidation = true
                 }
+                return node
             }
             node is BackwardsCompatNode -> {
                 node.element = next
@@ -747,9 +735,9 @@
 
 private fun <T : Modifier.Node> ModifierNodeElement<T>.updateUnsafe(
     node: Modifier.Node
-): Modifier.Node {
+) {
     @Suppress("UNCHECKED_CAST")
-    return update(node as T)
+    update(node as T)
 }
 
 private fun Modifier.fillVector(
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
index 3cc3011..b998c618 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
@@ -246,7 +246,7 @@
     // Don't invalidate the node if it marks itself as autoInvalidate = false.
     if (phase == Updated && !node.shouldAutoInvalidate) return
     if (Nodes.Layout in selfKindSet && node is LayoutModifierNode) {
-        node.invalidateMeasurements()
+        node.invalidateMeasurement()
         if (phase == Removed) {
             val coordinator = node.requireCoordinator(Nodes.Layout)
             coordinator.onRelease()
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsModifier.kt
index 4c340c7..1477974 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsModifier.kt
@@ -57,7 +57,7 @@
 
     override fun create() = CoreSemanticsModifierNode(semanticsConfiguration)
 
-    override fun update(node: CoreSemanticsModifierNode) = node
+    override fun update(node: CoreSemanticsModifierNode) {}
 
     override fun InspectorInfo.inspectableProperties() {
         // Nothing to inspect.
@@ -130,8 +130,8 @@
         return CoreSemanticsModifierNode(semanticsConfiguration)
     }
 
-    override fun update(node: CoreSemanticsModifierNode) = node.apply {
-        semanticsConfiguration = [email protected]
+    override fun update(node: CoreSemanticsModifierNode) {
+        node.semanticsConfiguration = semanticsConfiguration
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -179,8 +179,8 @@
         return CoreSemanticsModifierNode(semanticsConfiguration)
     }
 
-    override fun update(node: CoreSemanticsModifierNode) = node.apply {
-        semanticsConfiguration = this@ClearAndSetSemanticsModifierNodeElement.semanticsConfiguration
+    override fun update(node: CoreSemanticsModifierNode) {
+        node.semanticsConfiguration = semanticsConfiguration
     }
 
     override fun InspectorInfo.inspectableProperties() {
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/DelegatingNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/DelegatingNodeTest.kt
index 15c3ed5..2fc9795 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/DelegatingNodeTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/DelegatingNodeTest.kt
@@ -789,7 +789,7 @@
 
 internal data class NodeElement(val node: Modifier.Node) : ModifierNodeElement<Modifier.Node>() {
     override fun create(): Modifier.Node = node
-    override fun update(node: Modifier.Node): Modifier.Node = node
+    override fun update(node: Modifier.Node) {}
 }
 
 class Recorder : (Any) -> Unit {
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index 90f7edc..3a7a1c6 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -1393,7 +1393,7 @@
             private val node: Modifier.Node
         ) : ModifierNodeElement<Modifier.Node>() {
             override fun create() = node
-            override fun update(node: Modifier.Node) = node
+            override fun update(node: Modifier.Node) {}
         }
         val semanticsModifierElement1 = TestSemanticsModifierElement(semanticsModifier1)
         val semanticsModifierElement2 = TestSemanticsModifierElement(semanticsModifier2)
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierNodeElementTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierNodeElementTest.kt
index eeffd8a..63ecefa 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierNodeElementTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierNodeElementTest.kt
@@ -40,7 +40,7 @@
         ) : ModifierNodeElement<Modifier.Node>() {
             var classProperty = 0
             override fun create() = object : Modifier.Node() {}
-            override fun update(node: Modifier.Node) = node
+            override fun update(node: Modifier.Node) {}
             // We don't use equals or hashCode in this test, so bad implementations are okay.
             override fun hashCode() = 0
             override fun equals(other: Any?) = (this === other)
diff --git a/core/core-i18n/src/androidTest/java/androidx/core/i18n/CheckTheJavaApisTest.java b/core/core-i18n/src/androidTest/java/androidx/core/i18n/CheckTheJavaApisTest.java
index 23fa07b..f64ccb0 100644
--- a/core/core-i18n/src/androidTest/java/androidx/core/i18n/CheckTheJavaApisTest.java
+++ b/core/core-i18n/src/androidTest/java/androidx/core/i18n/CheckTheJavaApisTest.java
@@ -34,7 +34,6 @@
 import androidx.core.i18n.DateTimeFormatterSkeletonOptions.Year;
 import androidx.core.os.BuildCompat;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
@@ -86,12 +85,7 @@
     }
 
     @Test @SmallTest
-    @SdkSuppress(maxSdkVersion = 33) // b/262909049: Do not run this test on pre-release Android U.
     public void testSkeletonOptions() {
-        if (Build.VERSION.SDK_INT == 33 && !"REL".equals(Build.VERSION.CODENAME)) {
-            return; // b/262909049: Do not run this test on pre-release Android U.
-        }
-
         final DateTimeFormatterSkeletonOptions.Builder builder =
                 new DateTimeFormatterSkeletonOptions.Builder()
                         .setYear(Year.NUMERIC)
diff --git a/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatJdkStylesTest.kt b/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatJdkStylesTest.kt
index cead280..4f0a3ea 100644
--- a/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatJdkStylesTest.kt
+++ b/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatJdkStylesTest.kt
@@ -89,7 +89,9 @@
         val jdkFormatter = DateFormat.getTimeInstance(javaStyle, locale)
         val options = DateTimeFormatterJdkStyleOptions.createTimeInstance(javaStyle)
         val compatFormatter = DateTimeFormatter(options, locale)
-        assertEquals(jdkFormatter.format(testCalendar.time), compatFormatter.format(testCalendar))
+        assertEquals(
+            Helper.normalizeNnbsp(jdkFormatter.format(testCalendar.time)),
+            Helper.normalizeNnbsp(compatFormatter.format(testCalendar)))
     }
 
     private fun checkDateTime(
@@ -101,7 +103,9 @@
         val options =
             DateTimeFormatterJdkStyleOptions.createDateTimeInstance(javaDateStyle, javaTimeStyle)
         val compatFormatter = DateTimeFormatter(options, locale)
-        assertEquals(jdkFormatter.format(testCalendar.time), compatFormatter.format(testCalendar))
+        assertEquals(
+            Helper.normalizeNnbsp(jdkFormatter.format(testCalendar.time)),
+            Helper.normalizeNnbsp(compatFormatter.format(testCalendar)))
     }
 
     @Test @SmallTest
diff --git a/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterCommonOptionsTest.kt b/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterCommonOptionsTest.kt
index 265f46b..6860ebe 100644
--- a/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterCommonOptionsTest.kt
+++ b/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterCommonOptionsTest.kt
@@ -40,12 +40,7 @@
     )
 
     @Test @SmallTest
-    @SdkSuppress(maxSdkVersion = 33) // b/262909049: Do not run this test on pre-release Android U.
     fun test() {
-        if (Build.VERSION.SDK_INT == 33 && Build.VERSION.CODENAME != "REL") {
-            return // b/262909049: Do not run this test on pre-release Android U.
-        }
-
         val commonFormats = mapOf(
             DateTimeFormatterCommonOptions.ABBR_MONTH_WEEKDAY_DAY to "Sun, Sep 19",
             DateTimeFormatterCommonOptions.ABBR_MONTH_DAY to "Sep 19",
diff --git a/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterTest.kt b/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterTest.kt
index 3671c09..9534b9f 100644
--- a/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterTest.kt
+++ b/core/core-i18n/src/androidTest/java/androidx/core/i18n/DateTimeFormatterTest.kt
@@ -205,35 +205,29 @@
         val enUsForceH23 = Locale.forLanguageTag("en-US-u-hc-h23")
         val enUsForceH24 = Locale.forLanguageTag("en-US-u-hc-h24")
 
-        val expectedUs: String
-        val expectedUs11: String
-        val expectedUs12: String
-        val expectedUs23: String
-        val expectedUs24: String
-        // TODO: check this. Is `-u-hc-` not honored at all? File bug, maybe implement workaround.
-        if (BuildCompat.isAtLeastU()) {
-            expectedUs = "9:42:12\u202FPM"
-        } else {
-            expectedUs = "9:42:12 PM"
-        }
-        expectedUs11 = expectedUs
-        expectedUs12 = expectedUs
-        expectedUs23 = expectedUs
-        expectedUs24 = expectedUs
+        val expectedUs: String = "9:42:12 PM"
+        val expectedUs11: String = expectedUs
+        val expectedUs12: String = expectedUs
+        // TODO: check this. Is `-u-hc-` not honored at all?
+        // Official bug: https://unicode-org.atlassian.net/browse/ICU-11870
+        // It only manifests for the predefined formats (`DateFormat.MEDIUM` and so on),
+        // not for patterns generated from skeletons.
+        val expectedUs23: String = expectedUs
+        val expectedUs24: String = expectedUs
 
         var formatter: java.text.DateFormat
 
         // Formatting with style does not honor the uc overrides
         formatter = java.text.DateFormat.getTimeInstance(java.text.DateFormat.MEDIUM, Locale.US)
-        assertEquals(expectedUs, formatter.format(testMillis))
+        assertEquals(expectedUs, Helper.normalizeNnbsp(formatter.format(testMillis)))
         formatter = java.text.DateFormat.getTimeInstance(java.text.DateFormat.MEDIUM, enUsForceH11)
-        assertEquals(expectedUs11, formatter.format(testMillis))
+        assertEquals(expectedUs11, Helper.normalizeNnbsp(formatter.format(testMillis)))
         formatter = java.text.DateFormat.getTimeInstance(java.text.DateFormat.MEDIUM, enUsForceH12)
-        assertEquals(expectedUs12, formatter.format(testMillis))
+        assertEquals(expectedUs12, Helper.normalizeNnbsp(formatter.format(testMillis)))
         formatter = java.text.DateFormat.getTimeInstance(java.text.DateFormat.MEDIUM, enUsForceH23)
-        assertEquals(expectedUs23, formatter.format(testMillis))
+        assertEquals(expectedUs23, Helper.normalizeNnbsp(formatter.format(testMillis)))
         formatter = java.text.DateFormat.getTimeInstance(java.text.DateFormat.MEDIUM, enUsForceH24)
-        assertEquals(expectedUs24, formatter.format(testMillis))
+        assertEquals(expectedUs24, Helper.normalizeNnbsp(formatter.format(testMillis)))
     }
 
     @Test @SmallTest
diff --git a/core/core-i18n/src/androidTest/java/androidx/core/i18n/Helper.kt b/core/core-i18n/src/androidTest/java/androidx/core/i18n/Helper.kt
new file mode 100644
index 0000000..cea0afd5
--- /dev/null
+++ b/core/core-i18n/src/androidTest/java/androidx/core/i18n/Helper.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 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.core.i18n
+
+object Helper {
+    /*
+     * This method changes all instances of U+202F to U+0020.
+     *
+     * Android U takes ICU 71.1, which uses NNBSP (NARROW NO-BREAK SPACE, U+202F)
+     * betwee time and day cycle (for example 9:42\u202FPM)
+     *
+     * The Android `java.text.DateFormat` was patched to not use nnbsp (U+202F)
+     * in Android U, but ICU still returns times with U+202F.
+     * So this would give different results, but it is expected.
+     * In time this will probably go away (as the newer Android images propagate everywhere).
+     *
+     * And, since the patch happened without changing the Android version (pre-release),
+     * there are some Android U images that use space and some that use NNBSP.
+     * So testing the version is not enough to reliably tell if we will get.
+     */
+    fun normalizeNnbsp(text: String): String {
+        return text.replace("\u202F", " ")
+    }
+}
\ No newline at end of file
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 5b50848..9d411f1 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -885,7 +885,6 @@
   }
 
   public final class NotificationManagerCompat {
-    ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.TESTS) @VisibleForTesting protected NotificationManagerCompat(android.app.NotificationManager, android.content.Context);
     method public boolean areNotificationsEnabled();
     method public void cancel(int);
     method public void cancel(String?, int);
diff --git a/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutInfoCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutInfoCompatTest.java
index f9226fe..3628701c 100644
--- a/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutInfoCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutInfoCompatTest.java
@@ -524,4 +524,15 @@
         final ShortcutInfo shortcut = compat.toShortcutInfo();
         assertTrue(shortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER));
     }
+
+    @Test
+    public void testSetCategoriesAndAddCapabilityBinding() {
+        HashSet<String> categories = new HashSet<>();
+        categories.add("a");
+        mBuilder.setActivity(new ComponentName(mContext, TestActivity.class))
+                .setCategories(categories)
+                .addCapabilityBinding("b")
+                .build();
+        assertEquals(1, categories.size());
+    }
 }
diff --git a/core/core/src/androidTest/java/androidx/core/view/contentcapture/ContentCaptureSessionCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/contentcapture/ContentCaptureSessionCompatTest.java
index f342fa5..3c03635 100644
--- a/core/core/src/androidTest/java/androidx/core/view/contentcapture/ContentCaptureSessionCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/contentcapture/ContentCaptureSessionCompatTest.java
@@ -99,7 +99,8 @@
     }
 
     @Test
-    public void testNotifyViewsAppeared_throwsNPEAboveSDK29() {
+    @SdkSuppress(minSdkVersion = 29, maxSdkVersion = 33)
+    public void testNotifyViewsAppeared_throwsNPEBetweenSDK29And33() {
         ContentCaptureSession mockContentCaptureSession = mock(ContentCaptureSession.class);
         ViewStructure mockViewStructure = mock(ViewStructure.class);
         List<ViewStructure> viewStructures = new ArrayList<>();
diff --git a/core/core/src/main/java/androidx/core/app/NotificationManagerCompat.java b/core/core/src/main/java/androidx/core/app/NotificationManagerCompat.java
index 5ecfc5f..ae70ed1 100644
--- a/core/core/src/main/java/androidx/core/app/NotificationManagerCompat.java
+++ b/core/core/src/main/java/androidx/core/app/NotificationManagerCompat.java
@@ -17,7 +17,6 @@
 package androidx.core.app;
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
-import static androidx.annotation.RestrictTo.Scope.TESTS;
 
 import android.Manifest;
 import android.app.AppOpsManager;
@@ -222,9 +221,8 @@
                 Context.NOTIFICATION_SERVICE);
     }
 
-    @RestrictTo(TESTS)
     @VisibleForTesting
-    protected NotificationManagerCompat(@NonNull NotificationManager notificationManager,
+    NotificationManagerCompat(@NonNull NotificationManager notificationManager,
             @NonNull Context context) {
         mContext = context;
         mNotificationManager = notificationManager;
diff --git a/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java b/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
index b5b9106..0915eb8 100644
--- a/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
@@ -38,6 +38,7 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
+import androidx.collection.ArraySet;
 import androidx.core.app.Person;
 import androidx.core.content.LocusIdCompat;
 import androidx.core.graphics.drawable.IconCompat;
@@ -800,7 +801,9 @@
          */
         @NonNull
         public Builder setCategories(@NonNull Set<String> categories) {
-            mInfo.mCategories = categories;
+            ArraySet<String> set = new ArraySet<>();
+            set.addAll(categories);
+            mInfo.mCategories = set;
             return this;
         }
 
diff --git a/core/core/src/main/java/androidx/core/os/BuildCompat.java b/core/core/src/main/java/androidx/core/os/BuildCompat.java
index 7bed9ce..4dfca8e 100644
--- a/core/core/src/main/java/androidx/core/os/BuildCompat.java
+++ b/core/core/src/main/java/androidx/core/os/BuildCompat.java
@@ -27,7 +27,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RequiresOptIn;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 
 import java.util.Locale;
 
@@ -50,7 +50,7 @@
      *
      * @hide
      */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     protected static boolean isAtLeastPreReleaseCodename(@NonNull String codename,
             @NonNull String buildCodename) {
 
diff --git a/core/core/src/main/java/androidx/core/provider/FontsContractCompat.java b/core/core/src/main/java/androidx/core/provider/FontsContractCompat.java
index a1c9161..4f9487b 100644
--- a/core/core/src/main/java/androidx/core/provider/FontsContractCompat.java
+++ b/core/core/src/main/java/androidx/core/provider/FontsContractCompat.java
@@ -18,7 +18,6 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
-import static androidx.annotation.RestrictTo.Scope.TESTS;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -172,7 +171,6 @@
 
     /** @hide */
     @VisibleForTesting
-    @RestrictTo(TESTS)
     public static void resetTypefaceCache() {
         FontRequestWorker.resetTypefaceCache();
     }
diff --git a/core/core/src/main/java/androidx/core/view/SoftwareKeyboardControllerCompat.java b/core/core/src/main/java/androidx/core/view/SoftwareKeyboardControllerCompat.java
index 7d8bb31..a43c2af 100644
--- a/core/core/src/main/java/androidx/core/view/SoftwareKeyboardControllerCompat.java
+++ b/core/core/src/main/java/androidx/core/view/SoftwareKeyboardControllerCompat.java
@@ -228,7 +228,7 @@
                 insetsController.hide(WindowInsets.Type.ime());
             } else {
                 // Couldn't find an insets controller, fallback to old implementation
-                super.show();
+                super.hide();
             }
         }
     }
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderPlayServicesImpl.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderPlayServicesImpl.kt
index 594efb9..3524fe2 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderPlayServicesImpl.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderPlayServicesImpl.kt
@@ -21,7 +21,6 @@
 import android.os.CancellationSignal
 import android.util.Log
 import androidx.credentials.ClearCredentialStateRequest
-import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
 import androidx.credentials.CreateCredentialRequest
 import androidx.credentials.CreateCredentialResponse
@@ -52,8 +51,7 @@
 @Suppress("deprecation")
 class CredentialProviderPlayServicesImpl(private val context: Context) : CredentialProvider {
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    @set:RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     var googleApiAvailability = GoogleApiAvailability.getInstance()
     override fun onGetCredential(
         request: GetCredentialRequest,
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
index 94f8c4b..64039cd 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
@@ -134,7 +134,7 @@
             )
             return
         }
-        if (maybeReportErrorResultCodeGet(resultCode, TAG,
+        if (maybeReportErrorResultCodeGet(resultCode,
                 { s, f -> cancelOrCallbackExceptionOrResult(s, f) }, { e ->
                     this.executor.execute {
                         this.callback.onError(e)
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt
index 2755e88..a7b6746 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt
@@ -113,7 +113,7 @@
                 "$CONTROLLER_REQUEST_CODE which does not match what was given $uniqueRequestCode")
             return
         }
-        if (maybeReportErrorResultCodeCreate(resultCode, TAG,
+        if (maybeReportErrorResultCodeCreate(resultCode,
                 { s, f -> cancelOrCallbackExceptionOrResult(s, f) }, { e -> this.executor.execute {
                     this.callback.onError(e) } }, cancellationSignal)) return
         val response: CreateCredentialResponse = convertResponseToCredentialManager(Unit)
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt
index 46161e1..ac236eb 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt
@@ -134,7 +134,7 @@
                 "$CONTROLLER_REQUEST_CODE does not match what was given $uniqueRequestCode")
             return
         }
-        if (maybeReportErrorResultCodeCreate(resultCode, TAG,
+        if (maybeReportErrorResultCodeCreate(resultCode,
                 { s, f -> cancelOrCallbackExceptionOrResult(s, f) }, { e -> this.executor.execute {
                     this.callback.onError(e) } }, cancellationSignal)) return
         val bytes: ByteArray? = data?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CredentialProviderController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CredentialProviderController.kt
index 4278e5f..fafe63a 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CredentialProviderController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CredentialProviderController.kt
@@ -57,7 +57,6 @@
         @JvmStatic
         protected fun maybeReportErrorResultCodeCreate(
             resultCode: Int,
-            type: String,
             cancelOnError: (
                 CancellationSignal?,
                     () -> Unit
@@ -67,11 +66,11 @@
         ): Boolean {
             if (resultCode != Activity.RESULT_OK) {
                 var exception: CreateCredentialException = CreateCredentialUnknownException(
-                    generateErrorStringUnknown(type, resultCode)
+                    generateErrorStringUnknown(resultCode)
                 )
                 if (resultCode == Activity.RESULT_CANCELED) {
                     exception = CreateCredentialCancellationException(
-                        generateErrorStringCanceled(type)
+                        generateErrorStringCanceled()
                     )
                 }
                 cancelOnError(cancellationSignal) { onError(exception) }
@@ -80,12 +79,12 @@
             return false
         }
 
-        internal fun generateErrorStringUnknown(type: String, resultCode: Int): String {
-            return "$type activity with result code: $resultCode indicating not RESULT_OK"
+        internal fun generateErrorStringUnknown(resultCode: Int): String {
+            return "activity with result code: $resultCode indicating not RESULT_OK"
         }
 
-        internal fun generateErrorStringCanceled(type: String): String {
-            return "$type activity is cancelled by the user."
+        internal fun generateErrorStringCanceled(): String {
+            return "activity is cancelled by the user."
         }
 
         /**
@@ -96,7 +95,6 @@
         @JvmStatic
         protected fun maybeReportErrorResultCodeGet(
             resultCode: Int,
-            type: String,
             cancelOnError: (
                 CancellationSignal?,
                     () -> Unit
@@ -106,11 +104,11 @@
         ): Boolean {
             if (resultCode != Activity.RESULT_OK) {
                 var exception: GetCredentialException = GetCredentialUnknownException(
-                    generateErrorStringUnknown(type, resultCode)
+                    generateErrorStringUnknown(resultCode)
                 )
                 if (resultCode == Activity.RESULT_CANCELED) {
                     exception = GetCredentialCancellationException(
-                        generateErrorStringCanceled(type)
+                        generateErrorStringCanceled()
                     )
                 }
                 cancelOnError(cancellationSignal) { onError(exception) }
diff --git a/datastore/datastore-preferences-core/build.gradle b/datastore/datastore-preferences-core/build.gradle
index 34b4020..a9112b0 100644
--- a/datastore/datastore-preferences-core/build.gradle
+++ b/datastore/datastore-preferences-core/build.gradle
@@ -115,10 +115,7 @@
 )
 
 dependencies {
-    bundleInside(project(
-            path: ":datastore:datastore-preferences-proto",
-            configuration: "export"
-    ))
+    bundleInside(project(path: ":datastore:datastore-preferences-proto", configuration: "export"))
 }
 
 androidx {
diff --git a/development/build_log_simplifier/message-flakes.ignore b/development/build_log_simplifier/message-flakes.ignore
index 628f11c..5305b10 100644
--- a/development/build_log_simplifier/message-flakes.ignore
+++ b/development/build_log_simplifier/message-flakes.ignore
@@ -151,3 +151,5 @@
 Failed to compile with Kotlin daemon: java\.lang\.RuntimeException: Could not connect to Kotlin compile daemon
 Using fallback strategy: Compile without Kotlin daemon
 Try \./gradlew \-\-stop if this issue persists\.
+# b/ 279739438
+w\: Detected multiple Kotlin daemon sessions at kotlin/sessions
\ No newline at end of file
diff --git a/development/studio/studio.vmoptions b/development/studio/studio.vmoptions
index 6471f8c..2935f84 100644
--- a/development/studio/studio.vmoptions
+++ b/development/studio/studio.vmoptions
@@ -1,6 +1,6 @@
 -Xmx8g
 -Dappinspection.use.dev.jar=true
--Dlayout.inspector.rel.jar.location=../../../../../../out/androidx/compose/ui/ui-inspection/build/androidx_inspection/assembleInspectorJar/release
+-Dlayout.inspector.rel.jar.location=#studio/../../../../../../out/dist/inspection
 # https://github.com/google/google-java-format#intellij-jre-config
 --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
 --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
diff --git a/development/update_kotlin.sh b/development/update_kotlin.sh
new file mode 100755
index 0000000..a5c3673
--- /dev/null
+++ b/development/update_kotlin.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+set -e
+
+export KOTLIN_VERSION="1.9.0-dev-6188"
+
+# Download and place konan
+export KONAN_DIR=../../prebuilts/androidx/konan/nativeCompilerPrebuilts/dev/$KOTLIN_VERSION/linux-x86_64
+mkdir -p $KONAN_DIR
+curl -o $KONAN_DIR/kotlin-native-prebuilt-linux-x86_64-$KOTLIN_VERSION.tar.gz https://download-cf.jetbrains.com/kotlin/native/builds/dev/$KOTLIN_VERSION/linux-x86_64/kotlin-native-prebuilt-linux-x86_64-$KOTLIN_VERSION.tar.gz
+
+# Download maven artifacts
+ARTIFACTS_TO_DOWNLOAD="org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin.plugin.serialization:org.jetbrains.kotlin.plugin.serialization.gradle.plugin:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlinx-serialization-compiler-plugin-embeddable:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-test:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:$KOTLIN_VERSION"
+
+./development/importMaven/importMaven.sh --allow-jetbrains-dev "$ARTIFACTS_TO_DOWNLOAD"
diff --git a/development/update_studio.sh b/development/update_studio.sh
index 49bc4f7..87535ad 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -7,8 +7,8 @@
 
 # Get versions
 echo Getting Studio version and link
-AGP_VERSION=${1:-8.1.0-alpha11}
-STUDIO_VERSION_STRING=${2:-"Android Studio Giraffe | 2022.3.1 Canary 11"}
+AGP_VERSION=${1:-8.1.0-beta01}
+STUDIO_VERSION_STRING=${2:-"Android Studio Giraffe | 2022.3.1 Beta 1"}
 STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
 echo iframe link $STUDIO_IFRAME_LINK
 STUDIO_IFRAME_REDIRECT=`curl -s $STUDIO_IFRAME_LINK | grep href | sed 's/.*href="\([^"]*\)".*/\1/g'`
diff --git a/docs/onboarding.md b/docs/onboarding.md
index dc8f072..feb4b7d 100644
--- a/docs/onboarding.md
+++ b/docs/onboarding.md
@@ -785,20 +785,26 @@
 implementing bug fixes are expected to include new regression tests specific to
 the issue being fixed.
 
-### Running Tests
+### Running tests {#run-tests}
 
-#### Single Test Class or Method
+Generally, tests in the AndroidX repository should be run through the Android
+Studio UI. You can also run tests from the command line or via remote devices on
+FTL, see
+[Running unit and integration tests](/company/teams/androidx/testing.md#running)
+for details.
 
-1.  Open the desired test file in Android Studio.
-2.  Right-click on a test class or @Test method name and select `Run FooBarTest`
+#### Single test class or method
 
-#### Full Test Package
+1.  Open the desired test file in Android Studio
+2.  Right-click on a test class or `@Test` method name and select `Run <name>`
 
-1.  In the project side panel open the desired module.
-2.  Find the directory with the tests
-3.  Right-click on the directory and select `Run androidx.foobar`
+#### Full test package
 
-### Running Sample Apps
+1.  In the `Project` side panel, open the desired module
+2.  Find the package directory with the tests
+3.  Right-click on the directory and select `Run <package>`
+
+### Running sample apps {#run-samples}
 
 The AndroidX repository has a set of Android applications that exercise AndroidX
 code. These applications can be useful when you want to debug a real running
diff --git a/emoji2/emoji2-bundled/api/1.4.0-beta03.txt b/emoji2/emoji2-bundled/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..8749c28
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/1.4.0-beta03.txt
@@ -0,0 +1,9 @@
+// Signature format: 4.0
+package androidx.emoji2.bundled {
+
+  public class BundledEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public BundledEmojiCompatConfig(android.content.Context);
+  }
+
+}
+
diff --git a/emoji2/emoji2-bundled/api/public_plus_experimental_1.4.0-beta03.txt b/emoji2/emoji2-bundled/api/public_plus_experimental_1.4.0-beta03.txt
new file mode 100644
index 0000000..8749c28
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/public_plus_experimental_1.4.0-beta03.txt
@@ -0,0 +1,9 @@
+// Signature format: 4.0
+package androidx.emoji2.bundled {
+
+  public class BundledEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public BundledEmojiCompatConfig(android.content.Context);
+  }
+
+}
+
diff --git a/emoji2/emoji2-bundled/api/res-1.4.0-beta03.txt b/emoji2/emoji2-bundled/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/res-1.4.0-beta03.txt
diff --git a/emoji2/emoji2-bundled/api/restricted_1.4.0-beta03.txt b/emoji2/emoji2-bundled/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..8749c28
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,9 @@
+// Signature format: 4.0
+package androidx.emoji2.bundled {
+
+  public class BundledEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public BundledEmojiCompatConfig(android.content.Context);
+  }
+
+}
+
diff --git a/emoji2/emoji2-emojipicker/api/1.4.0-beta03.txt b/emoji2/emoji2-emojipicker/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..e2360fa
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/1.4.0-beta03.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.emoji2.emojipicker {
+
+  public final class EmojiPickerView extends android.widget.FrameLayout {
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs, optional int defStyleAttr);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs);
+    ctor public EmojiPickerView(android.content.Context context);
+    method public int getEmojiGridColumns();
+    method public float getEmojiGridRows();
+    method public void setEmojiGridColumns(int);
+    method public void setEmojiGridRows(float);
+    method public void setOnEmojiPickedListener(androidx.core.util.Consumer<androidx.emoji2.emojipicker.EmojiViewItem>? onEmojiPickedListener);
+    method public void setRecentEmojiProvider(androidx.emoji2.emojipicker.RecentEmojiProvider recentEmojiProvider);
+    property public final int emojiGridColumns;
+    property public final float emojiGridRows;
+  }
+
+  public final class EmojiViewItem {
+    ctor public EmojiViewItem(String emoji, java.util.List<java.lang.String> variants);
+    method public String getEmoji();
+    method public java.util.List<java.lang.String> getVariants();
+    property public final String emoji;
+    property public final java.util.List<java.lang.String> variants;
+  }
+
+  public interface RecentEmojiAsyncProvider {
+    method public com.google.common.util.concurrent.ListenableFuture<java.util.List<java.lang.String>> getRecentEmojiListAsync();
+    method public void recordSelection(String emoji);
+  }
+
+  public interface RecentEmojiProvider {
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<? extends java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+  public final class RecentEmojiProviderAdapter implements androidx.emoji2.emojipicker.RecentEmojiProvider {
+    ctor public RecentEmojiProviderAdapter(androidx.emoji2.emojipicker.RecentEmojiAsyncProvider recentEmojiAsyncProvider);
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<? extends java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+}
+
diff --git a/emoji2/emoji2-emojipicker/api/public_plus_experimental_1.4.0-beta03.txt b/emoji2/emoji2-emojipicker/api/public_plus_experimental_1.4.0-beta03.txt
new file mode 100644
index 0000000..e2360fa
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/public_plus_experimental_1.4.0-beta03.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.emoji2.emojipicker {
+
+  public final class EmojiPickerView extends android.widget.FrameLayout {
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs, optional int defStyleAttr);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs);
+    ctor public EmojiPickerView(android.content.Context context);
+    method public int getEmojiGridColumns();
+    method public float getEmojiGridRows();
+    method public void setEmojiGridColumns(int);
+    method public void setEmojiGridRows(float);
+    method public void setOnEmojiPickedListener(androidx.core.util.Consumer<androidx.emoji2.emojipicker.EmojiViewItem>? onEmojiPickedListener);
+    method public void setRecentEmojiProvider(androidx.emoji2.emojipicker.RecentEmojiProvider recentEmojiProvider);
+    property public final int emojiGridColumns;
+    property public final float emojiGridRows;
+  }
+
+  public final class EmojiViewItem {
+    ctor public EmojiViewItem(String emoji, java.util.List<java.lang.String> variants);
+    method public String getEmoji();
+    method public java.util.List<java.lang.String> getVariants();
+    property public final String emoji;
+    property public final java.util.List<java.lang.String> variants;
+  }
+
+  public interface RecentEmojiAsyncProvider {
+    method public com.google.common.util.concurrent.ListenableFuture<java.util.List<java.lang.String>> getRecentEmojiListAsync();
+    method public void recordSelection(String emoji);
+  }
+
+  public interface RecentEmojiProvider {
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<? extends java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+  public final class RecentEmojiProviderAdapter implements androidx.emoji2.emojipicker.RecentEmojiProvider {
+    ctor public RecentEmojiProviderAdapter(androidx.emoji2.emojipicker.RecentEmojiAsyncProvider recentEmojiAsyncProvider);
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<? extends java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+}
+
diff --git a/emoji2/emoji2-emojipicker/api/res-1.4.0-beta03.txt b/emoji2/emoji2-emojipicker/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/res-1.4.0-beta03.txt
diff --git a/emoji2/emoji2-emojipicker/api/restricted_1.4.0-beta03.txt b/emoji2/emoji2-emojipicker/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..e2360fa
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.emoji2.emojipicker {
+
+  public final class EmojiPickerView extends android.widget.FrameLayout {
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs, optional int defStyleAttr);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs);
+    ctor public EmojiPickerView(android.content.Context context);
+    method public int getEmojiGridColumns();
+    method public float getEmojiGridRows();
+    method public void setEmojiGridColumns(int);
+    method public void setEmojiGridRows(float);
+    method public void setOnEmojiPickedListener(androidx.core.util.Consumer<androidx.emoji2.emojipicker.EmojiViewItem>? onEmojiPickedListener);
+    method public void setRecentEmojiProvider(androidx.emoji2.emojipicker.RecentEmojiProvider recentEmojiProvider);
+    property public final int emojiGridColumns;
+    property public final float emojiGridRows;
+  }
+
+  public final class EmojiViewItem {
+    ctor public EmojiViewItem(String emoji, java.util.List<java.lang.String> variants);
+    method public String getEmoji();
+    method public java.util.List<java.lang.String> getVariants();
+    property public final String emoji;
+    property public final java.util.List<java.lang.String> variants;
+  }
+
+  public interface RecentEmojiAsyncProvider {
+    method public com.google.common.util.concurrent.ListenableFuture<java.util.List<java.lang.String>> getRecentEmojiListAsync();
+    method public void recordSelection(String emoji);
+  }
+
+  public interface RecentEmojiProvider {
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<? extends java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+  public final class RecentEmojiProviderAdapter implements androidx.emoji2.emojipicker.RecentEmojiProvider {
+    ctor public RecentEmojiProviderAdapter(androidx.emoji2.emojipicker.RecentEmojiAsyncProvider recentEmojiAsyncProvider);
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<? extends java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+}
+
diff --git a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt
index c6962da..94e4abc 100644
--- a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt
+++ b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt
@@ -112,7 +112,7 @@
                     .getDimensionPixelSize(R.dimen.emoji_picker_popup_view_elevation)
                     .toFloat()
             showAtLocation(
-                emojiView,
+                popupView,
                 Gravity.NO_GRAVITY,
                 x.roundToInt(),
                 y
diff --git a/emoji2/emoji2-emojipicker/src/main/res/values-zh-rHK/strings.xml b/emoji2/emoji2-emojipicker/src/main/res/values-zh-rHK/strings.xml
index d9694c0..d2befe8 100644
--- a/emoji2/emoji2-emojipicker/src/main/res/values-zh-rHK/strings.xml
+++ b/emoji2/emoji2-emojipicker/src/main/res/values-zh-rHK/strings.xml
@@ -28,5 +28,5 @@
     <string name="emoji_category_symbols" msgid="5626171724310261787">"符號"</string>
     <string name="emoji_category_flags" msgid="6185639503532784871">"旗幟"</string>
     <string name="emoji_empty_non_recent_category" msgid="288822832574892625">"沒有可用的 Emoji"</string>
-    <string name="emoji_empty_recent_category" msgid="7863877827879290200">"您尚未使用任何 Emoji"</string>
+    <string name="emoji_empty_recent_category" msgid="7863877827879290200">"你尚未使用任何 Emoji"</string>
 </resources>
diff --git a/emoji2/emoji2-views-helper/api/1.4.0-beta03.txt b/emoji2/emoji2-views-helper/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..30a6feb
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/1.4.0-beta03.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.emoji2.viewsintegration {
+
+  public final class EmojiEditTextHelper {
+    ctor public EmojiEditTextHelper(android.widget.EditText);
+    ctor public EmojiEditTextHelper(android.widget.EditText, boolean);
+    method public android.text.method.KeyListener? getKeyListener(android.text.method.KeyListener?);
+    method public int getMaxEmojiCount();
+    method public boolean isEnabled();
+    method public android.view.inputmethod.InputConnection? onCreateInputConnection(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo);
+    method public void setEnabled(boolean);
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public final class EmojiTextViewHelper {
+    ctor public EmojiTextViewHelper(android.widget.TextView);
+    ctor public EmojiTextViewHelper(android.widget.TextView, boolean);
+    method public android.text.InputFilter![] getFilters(android.text.InputFilter![]);
+    method public boolean isEnabled();
+    method public void setAllCaps(boolean);
+    method public void setEnabled(boolean);
+    method public void updateTransformationMethod();
+    method public android.text.method.TransformationMethod? wrapTransformationMethod(android.text.method.TransformationMethod?);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views-helper/api/public_plus_experimental_1.4.0-beta03.txt b/emoji2/emoji2-views-helper/api/public_plus_experimental_1.4.0-beta03.txt
new file mode 100644
index 0000000..30a6feb
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/public_plus_experimental_1.4.0-beta03.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.emoji2.viewsintegration {
+
+  public final class EmojiEditTextHelper {
+    ctor public EmojiEditTextHelper(android.widget.EditText);
+    ctor public EmojiEditTextHelper(android.widget.EditText, boolean);
+    method public android.text.method.KeyListener? getKeyListener(android.text.method.KeyListener?);
+    method public int getMaxEmojiCount();
+    method public boolean isEnabled();
+    method public android.view.inputmethod.InputConnection? onCreateInputConnection(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo);
+    method public void setEnabled(boolean);
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public final class EmojiTextViewHelper {
+    ctor public EmojiTextViewHelper(android.widget.TextView);
+    ctor public EmojiTextViewHelper(android.widget.TextView, boolean);
+    method public android.text.InputFilter![] getFilters(android.text.InputFilter![]);
+    method public boolean isEnabled();
+    method public void setAllCaps(boolean);
+    method public void setEnabled(boolean);
+    method public void updateTransformationMethod();
+    method public android.text.method.TransformationMethod? wrapTransformationMethod(android.text.method.TransformationMethod?);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views-helper/api/res-1.4.0-beta03.txt b/emoji2/emoji2-views-helper/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/res-1.4.0-beta03.txt
diff --git a/emoji2/emoji2-views-helper/api/restricted_1.4.0-beta03.txt b/emoji2/emoji2-views-helper/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..30a6feb
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.emoji2.viewsintegration {
+
+  public final class EmojiEditTextHelper {
+    ctor public EmojiEditTextHelper(android.widget.EditText);
+    ctor public EmojiEditTextHelper(android.widget.EditText, boolean);
+    method public android.text.method.KeyListener? getKeyListener(android.text.method.KeyListener?);
+    method public int getMaxEmojiCount();
+    method public boolean isEnabled();
+    method public android.view.inputmethod.InputConnection? onCreateInputConnection(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo);
+    method public void setEnabled(boolean);
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public final class EmojiTextViewHelper {
+    ctor public EmojiTextViewHelper(android.widget.TextView);
+    ctor public EmojiTextViewHelper(android.widget.TextView, boolean);
+    method public android.text.InputFilter![] getFilters(android.text.InputFilter![]);
+    method public boolean isEnabled();
+    method public void setAllCaps(boolean);
+    method public void setEnabled(boolean);
+    method public void updateTransformationMethod();
+    method public android.text.method.TransformationMethod? wrapTransformationMethod(android.text.method.TransformationMethod?);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views/api/1.4.0-beta03.txt b/emoji2/emoji2-views/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..879b30e
--- /dev/null
+++ b/emoji2/emoji2-views/api/1.4.0-beta03.txt
@@ -0,0 +1,34 @@
+// Signature format: 4.0
+package androidx.emoji2.widget {
+
+  public class EmojiButton extends android.widget.Button {
+    ctor public EmojiButton(android.content.Context);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+  public class EmojiEditText extends android.widget.EditText {
+    ctor public EmojiEditText(android.content.Context);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?, int);
+    method public int getMaxEmojiCount();
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public class EmojiExtractTextLayout extends android.widget.LinearLayout {
+    ctor public EmojiExtractTextLayout(android.content.Context);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public int getEmojiReplaceStrategy();
+    method public void onUpdateExtractingViews(android.inputmethodservice.InputMethodService, android.view.inputmethod.EditorInfo);
+    method public void setEmojiReplaceStrategy(int);
+  }
+
+  public class EmojiTextView extends android.widget.TextView {
+    ctor public EmojiTextView(android.content.Context);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views/api/public_plus_experimental_1.4.0-beta03.txt b/emoji2/emoji2-views/api/public_plus_experimental_1.4.0-beta03.txt
new file mode 100644
index 0000000..879b30e
--- /dev/null
+++ b/emoji2/emoji2-views/api/public_plus_experimental_1.4.0-beta03.txt
@@ -0,0 +1,34 @@
+// Signature format: 4.0
+package androidx.emoji2.widget {
+
+  public class EmojiButton extends android.widget.Button {
+    ctor public EmojiButton(android.content.Context);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+  public class EmojiEditText extends android.widget.EditText {
+    ctor public EmojiEditText(android.content.Context);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?, int);
+    method public int getMaxEmojiCount();
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public class EmojiExtractTextLayout extends android.widget.LinearLayout {
+    ctor public EmojiExtractTextLayout(android.content.Context);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public int getEmojiReplaceStrategy();
+    method public void onUpdateExtractingViews(android.inputmethodservice.InputMethodService, android.view.inputmethod.EditorInfo);
+    method public void setEmojiReplaceStrategy(int);
+  }
+
+  public class EmojiTextView extends android.widget.TextView {
+    ctor public EmojiTextView(android.content.Context);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views/api/res-1.4.0-beta03.txt b/emoji2/emoji2-views/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..8bc8423
--- /dev/null
+++ b/emoji2/emoji2-views/api/res-1.4.0-beta03.txt
@@ -0,0 +1,2 @@
+attr emojiReplaceStrategy
+attr maxEmojiCount
diff --git a/emoji2/emoji2-views/api/restricted_1.4.0-beta03.txt b/emoji2/emoji2-views/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..879b30e
--- /dev/null
+++ b/emoji2/emoji2-views/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,34 @@
+// Signature format: 4.0
+package androidx.emoji2.widget {
+
+  public class EmojiButton extends android.widget.Button {
+    ctor public EmojiButton(android.content.Context);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+  public class EmojiEditText extends android.widget.EditText {
+    ctor public EmojiEditText(android.content.Context);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?, int);
+    method public int getMaxEmojiCount();
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public class EmojiExtractTextLayout extends android.widget.LinearLayout {
+    ctor public EmojiExtractTextLayout(android.content.Context);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public int getEmojiReplaceStrategy();
+    method public void onUpdateExtractingViews(android.inputmethodservice.InputMethodService, android.view.inputmethod.EditorInfo);
+    method public void setEmojiReplaceStrategy(int);
+  }
+
+  public class EmojiTextView extends android.widget.TextView {
+    ctor public EmojiTextView(android.content.Context);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+}
+
diff --git a/emoji2/emoji2/api/1.4.0-beta03.txt b/emoji2/emoji2/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..11d9335
--- /dev/null
+++ b/emoji2/emoji2/api/1.4.0-beta03.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.emoji2.text {
+
+  public final class DefaultEmojiCompatConfig {
+    method public static androidx.emoji2.text.FontRequestEmojiCompatConfig? create(android.content.Context);
+  }
+
+  @AnyThread public class EmojiCompat {
+    method public static androidx.emoji2.text.EmojiCompat get();
+    method public String getAssetSignature();
+    method public int getEmojiEnd(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiMatch(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiStart(CharSequence, @IntRange(from=0) int);
+    method public int getLoadState();
+    method public static boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection, android.text.Editable, @IntRange(from=0) int, @IntRange(from=0) int, boolean);
+    method public static boolean handleOnKeyDown(android.text.Editable, int, android.view.KeyEvent);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence, @IntRange(from=0) int);
+    method public static androidx.emoji2.text.EmojiCompat? init(android.content.Context);
+    method public static androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config);
+    method public static boolean isConfigured();
+    method public void load();
+    method @CheckResult public CharSequence? process(CharSequence?);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, int);
+    method public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void updateEditorInfo(android.view.inputmethod.EditorInfo);
+    field public static final String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
+    field public static final String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
+    field public static final int EMOJI_FALLBACK = 2; // 0x2
+    field public static final int EMOJI_SUPPORTED = 1; // 0x1
+    field public static final int EMOJI_UNSUPPORTED = 0; // 0x0
+    field public static final int LOAD_STATE_DEFAULT = 3; // 0x3
+    field public static final int LOAD_STATE_FAILED = 2; // 0x2
+    field public static final int LOAD_STATE_LOADING = 0; // 0x0
+    field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+    field public static final int LOAD_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int LOAD_STRATEGY_MANUAL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
+  }
+
+  public abstract static class EmojiCompat.Config {
+    ctor protected EmojiCompat.Config(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader);
+    method protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader();
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(@ColorInt int);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker);
+    method public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int);
+    method public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer!>?);
+    method public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+  }
+
+  public static interface EmojiCompat.GlyphChecker {
+    method public boolean hasGlyph(CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+  }
+
+  public abstract static class EmojiCompat.InitCallback {
+    ctor public EmojiCompat.InitCallback();
+    method public void onFailed(Throwable?);
+    method public void onInitialized();
+  }
+
+  public static interface EmojiCompat.MetadataRepoLoader {
+    method public void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback);
+  }
+
+  public abstract static class EmojiCompat.MetadataRepoLoaderCallback {
+    ctor public EmojiCompat.MetadataRepoLoaderCallback();
+    method public abstract void onFailed(Throwable?);
+    method public abstract void onLoaded(androidx.emoji2.text.MetadataRepo);
+  }
+
+  public static interface EmojiCompat.SpanFactory {
+    method @RequiresApi(19) public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer);
+  }
+
+  public class EmojiCompatInitializer implements androidx.startup.Initializer<java.lang.Boolean> {
+    ctor public EmojiCompatInitializer();
+    method public Boolean create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  @RequiresApi(19) public abstract class EmojiSpan extends android.text.style.ReplacementSpan {
+    method public int getSize(android.graphics.Paint, CharSequence!, int, int, android.graphics.Paint.FontMetricsInt?);
+    method public final androidx.emoji2.text.TypefaceEmojiRasterizer getTypefaceRasterizer();
+  }
+
+  public class FontRequestEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public FontRequestEmojiCompatConfig(android.content.Context, androidx.core.provider.FontRequest);
+    method @Deprecated public androidx.emoji2.text.FontRequestEmojiCompatConfig setHandler(android.os.Handler?);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setLoadingExecutor(java.util.concurrent.Executor);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setRetryPolicy(androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy?);
+  }
+
+  public static class FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy extends androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy(long);
+    method public long getRetryDelay();
+  }
+
+  public abstract static class FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.RetryPolicy();
+    method public abstract long getRetryDelay();
+  }
+
+  @AnyThread @RequiresApi(19) public final class MetadataRepo {
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.io.InputStream) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.nio.ByteBuffer) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.content.res.AssetManager, String) throws java.io.IOException;
+  }
+
+  @AnyThread @RequiresApi(19) public class TypefaceEmojiRasterizer {
+    method public void draw(android.graphics.Canvas, float, float, android.graphics.Paint);
+    method public int getCodepointAt(int);
+    method public int getCodepointsLength();
+    method public int getHeight();
+    method public android.graphics.Typeface getTypeface();
+    method public int getWidth();
+    method public boolean isDefaultEmoji();
+    method public boolean isPreferredSystemRender();
+  }
+
+}
+
diff --git a/emoji2/emoji2/api/public_plus_experimental_1.4.0-beta03.txt b/emoji2/emoji2/api/public_plus_experimental_1.4.0-beta03.txt
new file mode 100644
index 0000000..11d9335
--- /dev/null
+++ b/emoji2/emoji2/api/public_plus_experimental_1.4.0-beta03.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.emoji2.text {
+
+  public final class DefaultEmojiCompatConfig {
+    method public static androidx.emoji2.text.FontRequestEmojiCompatConfig? create(android.content.Context);
+  }
+
+  @AnyThread public class EmojiCompat {
+    method public static androidx.emoji2.text.EmojiCompat get();
+    method public String getAssetSignature();
+    method public int getEmojiEnd(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiMatch(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiStart(CharSequence, @IntRange(from=0) int);
+    method public int getLoadState();
+    method public static boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection, android.text.Editable, @IntRange(from=0) int, @IntRange(from=0) int, boolean);
+    method public static boolean handleOnKeyDown(android.text.Editable, int, android.view.KeyEvent);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence, @IntRange(from=0) int);
+    method public static androidx.emoji2.text.EmojiCompat? init(android.content.Context);
+    method public static androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config);
+    method public static boolean isConfigured();
+    method public void load();
+    method @CheckResult public CharSequence? process(CharSequence?);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, int);
+    method public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void updateEditorInfo(android.view.inputmethod.EditorInfo);
+    field public static final String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
+    field public static final String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
+    field public static final int EMOJI_FALLBACK = 2; // 0x2
+    field public static final int EMOJI_SUPPORTED = 1; // 0x1
+    field public static final int EMOJI_UNSUPPORTED = 0; // 0x0
+    field public static final int LOAD_STATE_DEFAULT = 3; // 0x3
+    field public static final int LOAD_STATE_FAILED = 2; // 0x2
+    field public static final int LOAD_STATE_LOADING = 0; // 0x0
+    field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+    field public static final int LOAD_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int LOAD_STRATEGY_MANUAL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
+  }
+
+  public abstract static class EmojiCompat.Config {
+    ctor protected EmojiCompat.Config(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader);
+    method protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader();
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(@ColorInt int);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker);
+    method public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int);
+    method public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer!>?);
+    method public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+  }
+
+  public static interface EmojiCompat.GlyphChecker {
+    method public boolean hasGlyph(CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+  }
+
+  public abstract static class EmojiCompat.InitCallback {
+    ctor public EmojiCompat.InitCallback();
+    method public void onFailed(Throwable?);
+    method public void onInitialized();
+  }
+
+  public static interface EmojiCompat.MetadataRepoLoader {
+    method public void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback);
+  }
+
+  public abstract static class EmojiCompat.MetadataRepoLoaderCallback {
+    ctor public EmojiCompat.MetadataRepoLoaderCallback();
+    method public abstract void onFailed(Throwable?);
+    method public abstract void onLoaded(androidx.emoji2.text.MetadataRepo);
+  }
+
+  public static interface EmojiCompat.SpanFactory {
+    method @RequiresApi(19) public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer);
+  }
+
+  public class EmojiCompatInitializer implements androidx.startup.Initializer<java.lang.Boolean> {
+    ctor public EmojiCompatInitializer();
+    method public Boolean create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  @RequiresApi(19) public abstract class EmojiSpan extends android.text.style.ReplacementSpan {
+    method public int getSize(android.graphics.Paint, CharSequence!, int, int, android.graphics.Paint.FontMetricsInt?);
+    method public final androidx.emoji2.text.TypefaceEmojiRasterizer getTypefaceRasterizer();
+  }
+
+  public class FontRequestEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public FontRequestEmojiCompatConfig(android.content.Context, androidx.core.provider.FontRequest);
+    method @Deprecated public androidx.emoji2.text.FontRequestEmojiCompatConfig setHandler(android.os.Handler?);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setLoadingExecutor(java.util.concurrent.Executor);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setRetryPolicy(androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy?);
+  }
+
+  public static class FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy extends androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy(long);
+    method public long getRetryDelay();
+  }
+
+  public abstract static class FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.RetryPolicy();
+    method public abstract long getRetryDelay();
+  }
+
+  @AnyThread @RequiresApi(19) public final class MetadataRepo {
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.io.InputStream) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.nio.ByteBuffer) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.content.res.AssetManager, String) throws java.io.IOException;
+  }
+
+  @AnyThread @RequiresApi(19) public class TypefaceEmojiRasterizer {
+    method public void draw(android.graphics.Canvas, float, float, android.graphics.Paint);
+    method public int getCodepointAt(int);
+    method public int getCodepointsLength();
+    method public int getHeight();
+    method public android.graphics.Typeface getTypeface();
+    method public int getWidth();
+    method public boolean isDefaultEmoji();
+    method public boolean isPreferredSystemRender();
+  }
+
+}
+
diff --git a/emoji2/emoji2/api/res-1.4.0-beta03.txt b/emoji2/emoji2/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2/api/res-1.4.0-beta03.txt
diff --git a/emoji2/emoji2/api/restricted_1.4.0-beta03.txt b/emoji2/emoji2/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..11d9335
--- /dev/null
+++ b/emoji2/emoji2/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.emoji2.text {
+
+  public final class DefaultEmojiCompatConfig {
+    method public static androidx.emoji2.text.FontRequestEmojiCompatConfig? create(android.content.Context);
+  }
+
+  @AnyThread public class EmojiCompat {
+    method public static androidx.emoji2.text.EmojiCompat get();
+    method public String getAssetSignature();
+    method public int getEmojiEnd(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiMatch(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiStart(CharSequence, @IntRange(from=0) int);
+    method public int getLoadState();
+    method public static boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection, android.text.Editable, @IntRange(from=0) int, @IntRange(from=0) int, boolean);
+    method public static boolean handleOnKeyDown(android.text.Editable, int, android.view.KeyEvent);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence, @IntRange(from=0) int);
+    method public static androidx.emoji2.text.EmojiCompat? init(android.content.Context);
+    method public static androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config);
+    method public static boolean isConfigured();
+    method public void load();
+    method @CheckResult public CharSequence? process(CharSequence?);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, int);
+    method public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void updateEditorInfo(android.view.inputmethod.EditorInfo);
+    field public static final String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
+    field public static final String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
+    field public static final int EMOJI_FALLBACK = 2; // 0x2
+    field public static final int EMOJI_SUPPORTED = 1; // 0x1
+    field public static final int EMOJI_UNSUPPORTED = 0; // 0x0
+    field public static final int LOAD_STATE_DEFAULT = 3; // 0x3
+    field public static final int LOAD_STATE_FAILED = 2; // 0x2
+    field public static final int LOAD_STATE_LOADING = 0; // 0x0
+    field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+    field public static final int LOAD_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int LOAD_STRATEGY_MANUAL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
+  }
+
+  public abstract static class EmojiCompat.Config {
+    ctor protected EmojiCompat.Config(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader);
+    method protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader();
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(@ColorInt int);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker);
+    method public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int);
+    method public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer!>?);
+    method public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+  }
+
+  public static interface EmojiCompat.GlyphChecker {
+    method public boolean hasGlyph(CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+  }
+
+  public abstract static class EmojiCompat.InitCallback {
+    ctor public EmojiCompat.InitCallback();
+    method public void onFailed(Throwable?);
+    method public void onInitialized();
+  }
+
+  public static interface EmojiCompat.MetadataRepoLoader {
+    method public void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback);
+  }
+
+  public abstract static class EmojiCompat.MetadataRepoLoaderCallback {
+    ctor public EmojiCompat.MetadataRepoLoaderCallback();
+    method public abstract void onFailed(Throwable?);
+    method public abstract void onLoaded(androidx.emoji2.text.MetadataRepo);
+  }
+
+  public static interface EmojiCompat.SpanFactory {
+    method @RequiresApi(19) public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer);
+  }
+
+  public class EmojiCompatInitializer implements androidx.startup.Initializer<java.lang.Boolean> {
+    ctor public EmojiCompatInitializer();
+    method public Boolean create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  @RequiresApi(19) public abstract class EmojiSpan extends android.text.style.ReplacementSpan {
+    method public int getSize(android.graphics.Paint, CharSequence!, int, int, android.graphics.Paint.FontMetricsInt?);
+    method public final androidx.emoji2.text.TypefaceEmojiRasterizer getTypefaceRasterizer();
+  }
+
+  public class FontRequestEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public FontRequestEmojiCompatConfig(android.content.Context, androidx.core.provider.FontRequest);
+    method @Deprecated public androidx.emoji2.text.FontRequestEmojiCompatConfig setHandler(android.os.Handler?);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setLoadingExecutor(java.util.concurrent.Executor);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setRetryPolicy(androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy?);
+  }
+
+  public static class FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy extends androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy(long);
+    method public long getRetryDelay();
+  }
+
+  public abstract static class FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.RetryPolicy();
+    method public abstract long getRetryDelay();
+  }
+
+  @AnyThread @RequiresApi(19) public final class MetadataRepo {
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.io.InputStream) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.nio.ByteBuffer) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.content.res.AssetManager, String) throws java.io.IOException;
+  }
+
+  @AnyThread @RequiresApi(19) public class TypefaceEmojiRasterizer {
+    method public void draw(android.graphics.Canvas, float, float, android.graphics.Paint);
+    method public int getCodepointAt(int);
+    method public int getCodepointsLength();
+    method public int getHeight();
+    method public android.graphics.Typeface getTypeface();
+    method public int getWidth();
+    method public boolean isDefaultEmoji();
+    method public boolean isPreferredSystemRender();
+  }
+
+}
+
diff --git a/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiCompat.java b/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiCompat.java
index 7de9f8f..18907b9 100644
--- a/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiCompat.java
+++ b/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiCompat.java
@@ -17,7 +17,6 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-import static androidx.annotation.RestrictTo.Scope.TESTS;
 
 import android.app.Application;
 import android.content.Context;
@@ -43,6 +42,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.collection.ArraySet;
 import androidx.core.util.Preconditions;
 
@@ -618,7 +618,7 @@
      *
      * @hide
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     @Nullable
     public static EmojiCompat reset(@Nullable final EmojiCompat emojiCompat) {
         synchronized (INSTANCE_LOCK) {
@@ -632,7 +632,7 @@
      *
      * @hide
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     public static void skipDefaultConfigurationLookup(boolean shouldSkip) {
         synchronized (CONFIG_LOCK) {
             sHasDoneDefaultConfigLookup = shouldSkip;
diff --git a/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiSpan.java b/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiSpan.java
index 7c334c6..5c0af43 100644
--- a/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiSpan.java
+++ b/emoji2/emoji2/src/main/java/androidx/emoji2/text/EmojiSpan.java
@@ -16,7 +16,6 @@
 package androidx.emoji2.text;
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
-import static androidx.annotation.RestrictTo.Scope.TESTS;
 
 import android.annotation.SuppressLint;
 import android.graphics.Paint;
@@ -26,6 +25,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.core.util.Preconditions;
 
 /**
@@ -125,7 +125,7 @@
      *
      * @hide
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     public final int getHeight() {
         return mHeight;
     }
@@ -143,7 +143,7 @@
      *
      * @hide
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     public final int getId() {
         return getTypefaceRasterizer().getId();
     }
diff --git a/emoji2/emoji2/src/main/java/androidx/emoji2/text/MetadataRepo.java b/emoji2/emoji2/src/main/java/androidx/emoji2/text/MetadataRepo.java
index f08ae06..35e7fb8 100644
--- a/emoji2/emoji2/src/main/java/androidx/emoji2/text/MetadataRepo.java
+++ b/emoji2/emoji2/src/main/java/androidx/emoji2/text/MetadataRepo.java
@@ -88,7 +88,7 @@
      * @hide
      */
     @NonNull
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     public static MetadataRepo create(@NonNull final Typeface typeface) {
         try {
             TraceCompat.beginSection(S_TRACE_CREATE_REPO);
diff --git a/emoji2/emoji2/src/main/java/androidx/emoji2/text/TypefaceEmojiRasterizer.java b/emoji2/emoji2/src/main/java/androidx/emoji2/text/TypefaceEmojiRasterizer.java
index f120b3c..c505d27 100644
--- a/emoji2/emoji2/src/main/java/androidx/emoji2/text/TypefaceEmojiRasterizer.java
+++ b/emoji2/emoji2/src/main/java/androidx/emoji2/text/TypefaceEmojiRasterizer.java
@@ -17,7 +17,6 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-import static androidx.annotation.RestrictTo.Scope.TESTS;
 
 import android.annotation.SuppressLint;
 import android.graphics.Canvas;
@@ -30,6 +29,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.emoji2.text.flatbuffer.MetadataItem;
 import androidx.emoji2.text.flatbuffer.MetadataList;
 
@@ -235,7 +235,7 @@
      *
      * @hide
      */
-    @RestrictTo(TESTS)
+    @VisibleForTesting
     public void resetHasGlyphCache() {
         boolean willExclude = isPreferredSystemRender();
         if (willExclude) {
diff --git a/fragment/fragment-ktx/api/1.6.0-beta02.txt b/fragment/fragment-ktx/api/1.6.0-beta02.txt
new file mode 100644
index 0000000..b93e06b
--- /dev/null
+++ b/fragment/fragment-ktx/api/1.6.0-beta02.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.fragment.app {
+
+  public final class FragmentKt {
+    method public static void clearFragmentResult(androidx.fragment.app.Fragment, String requestKey);
+    method public static void clearFragmentResultListener(androidx.fragment.app.Fragment, String requestKey);
+    method public static void setFragmentResult(androidx.fragment.app.Fragment, String requestKey, android.os.Bundle result);
+    method public static void setFragmentResultListener(androidx.fragment.app.Fragment, String requestKey, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+  }
+
+  public final class FragmentManagerKt {
+    method public static inline void commit(androidx.fragment.app.FragmentManager, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+    method @MainThread public static inline void commitNow(androidx.fragment.app.FragmentManager, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+    method @Deprecated public static inline void transaction(androidx.fragment.app.FragmentManager, optional boolean now, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+  }
+
+  public final class FragmentTransactionKt {
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, optional String? tag, optional android.os.Bundle? args);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.FragmentTransaction, String tag, optional android.os.Bundle? args);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction replace(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, optional String? tag, optional android.os.Bundle? args);
+  }
+
+  public final class FragmentViewModelLazyKt {
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+  public final class ViewKt {
+    method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+  }
+
+}
+
diff --git a/fragment/fragment-ktx/api/public_plus_experimental_1.6.0-beta02.txt b/fragment/fragment-ktx/api/public_plus_experimental_1.6.0-beta02.txt
new file mode 100644
index 0000000..b93e06b
--- /dev/null
+++ b/fragment/fragment-ktx/api/public_plus_experimental_1.6.0-beta02.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.fragment.app {
+
+  public final class FragmentKt {
+    method public static void clearFragmentResult(androidx.fragment.app.Fragment, String requestKey);
+    method public static void clearFragmentResultListener(androidx.fragment.app.Fragment, String requestKey);
+    method public static void setFragmentResult(androidx.fragment.app.Fragment, String requestKey, android.os.Bundle result);
+    method public static void setFragmentResultListener(androidx.fragment.app.Fragment, String requestKey, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+  }
+
+  public final class FragmentManagerKt {
+    method public static inline void commit(androidx.fragment.app.FragmentManager, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+    method @MainThread public static inline void commitNow(androidx.fragment.app.FragmentManager, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+    method @Deprecated public static inline void transaction(androidx.fragment.app.FragmentManager, optional boolean now, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+  }
+
+  public final class FragmentTransactionKt {
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, optional String? tag, optional android.os.Bundle? args);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.FragmentTransaction, String tag, optional android.os.Bundle? args);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction replace(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, optional String? tag, optional android.os.Bundle? args);
+  }
+
+  public final class FragmentViewModelLazyKt {
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+  public final class ViewKt {
+    method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+  }
+
+}
+
diff --git a/fragment/fragment-ktx/api/res-1.6.0-beta02.txt b/fragment/fragment-ktx/api/res-1.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment-ktx/api/res-1.6.0-beta02.txt
diff --git a/fragment/fragment-ktx/api/restricted_1.6.0-beta02.txt b/fragment/fragment-ktx/api/restricted_1.6.0-beta02.txt
new file mode 100644
index 0000000..b93e06b
--- /dev/null
+++ b/fragment/fragment-ktx/api/restricted_1.6.0-beta02.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.fragment.app {
+
+  public final class FragmentKt {
+    method public static void clearFragmentResult(androidx.fragment.app.Fragment, String requestKey);
+    method public static void clearFragmentResultListener(androidx.fragment.app.Fragment, String requestKey);
+    method public static void setFragmentResult(androidx.fragment.app.Fragment, String requestKey, android.os.Bundle result);
+    method public static void setFragmentResultListener(androidx.fragment.app.Fragment, String requestKey, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+  }
+
+  public final class FragmentManagerKt {
+    method public static inline void commit(androidx.fragment.app.FragmentManager, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+    method @MainThread public static inline void commitNow(androidx.fragment.app.FragmentManager, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+    method @Deprecated public static inline void transaction(androidx.fragment.app.FragmentManager, optional boolean now, optional boolean allowStateLoss, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+  }
+
+  public final class FragmentTransactionKt {
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, optional String? tag, optional android.os.Bundle? args);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.FragmentTransaction, String tag, optional android.os.Bundle? args);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.FragmentTransaction replace(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, optional String? tag, optional android.os.Bundle? args);
+  }
+
+  public final class FragmentViewModelLazyKt {
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+  public final class ViewKt {
+    method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+  }
+
+}
+
diff --git a/fragment/fragment-testing-manifest/api/1.6.0-beta02.txt b/fragment/fragment-testing-manifest/api/1.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/1.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/fragment/fragment-testing-manifest/api/public_plus_experimental_1.6.0-beta02.txt b/fragment/fragment-testing-manifest/api/public_plus_experimental_1.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/public_plus_experimental_1.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/fragment/fragment-testing-manifest/api/res-1.6.0-beta02.txt b/fragment/fragment-testing-manifest/api/res-1.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/res-1.6.0-beta02.txt
diff --git a/fragment/fragment-testing-manifest/api/restricted_1.6.0-beta02.txt b/fragment/fragment-testing-manifest/api/restricted_1.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/restricted_1.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/fragment/fragment-testing/api/1.6.0-beta02.txt b/fragment/fragment-testing/api/1.6.0-beta02.txt
new file mode 100644
index 0000000..d5c260e
--- /dev/null
+++ b/fragment/fragment-testing/api/1.6.0-beta02.txt
@@ -0,0 +1,60 @@
+// Signature format: 4.0
+package androidx.fragment.app.testing {
+
+  public final class FragmentScenario<F extends androidx.fragment.app.Fragment> implements java.io.Closeable {
+    method public void close();
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass);
+    method public androidx.fragment.app.testing.FragmentScenario<F> moveToState(androidx.lifecycle.Lifecycle.State newState);
+    method public androidx.fragment.app.testing.FragmentScenario<F> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F> action);
+    method public androidx.fragment.app.testing.FragmentScenario<F> recreate();
+    field public static final androidx.fragment.app.testing.FragmentScenario.Companion Companion;
+  }
+
+  public static final class FragmentScenario.Companion {
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass);
+  }
+
+  public static fun interface FragmentScenario.FragmentAction<F extends androidx.fragment.app.Fragment> {
+    method public void perform(F fragment);
+  }
+
+  public final class FragmentScenarioKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.fragment.app.FragmentFactory? factory);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.fragment.app.FragmentFactory? factory);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, T> T withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
+  }
+
+}
+
diff --git a/fragment/fragment-testing/api/public_plus_experimental_1.6.0-beta02.txt b/fragment/fragment-testing/api/public_plus_experimental_1.6.0-beta02.txt
new file mode 100644
index 0000000..d5c260e
--- /dev/null
+++ b/fragment/fragment-testing/api/public_plus_experimental_1.6.0-beta02.txt
@@ -0,0 +1,60 @@
+// Signature format: 4.0
+package androidx.fragment.app.testing {
+
+  public final class FragmentScenario<F extends androidx.fragment.app.Fragment> implements java.io.Closeable {
+    method public void close();
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass);
+    method public androidx.fragment.app.testing.FragmentScenario<F> moveToState(androidx.lifecycle.Lifecycle.State newState);
+    method public androidx.fragment.app.testing.FragmentScenario<F> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F> action);
+    method public androidx.fragment.app.testing.FragmentScenario<F> recreate();
+    field public static final androidx.fragment.app.testing.FragmentScenario.Companion Companion;
+  }
+
+  public static final class FragmentScenario.Companion {
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass);
+  }
+
+  public static fun interface FragmentScenario.FragmentAction<F extends androidx.fragment.app.Fragment> {
+    method public void perform(F fragment);
+  }
+
+  public final class FragmentScenarioKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.fragment.app.FragmentFactory? factory);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.fragment.app.FragmentFactory? factory);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, T> T withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
+  }
+
+}
+
diff --git a/fragment/fragment-testing/api/res-1.6.0-beta02.txt b/fragment/fragment-testing/api/res-1.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment-testing/api/res-1.6.0-beta02.txt
diff --git a/fragment/fragment-testing/api/restricted_1.6.0-beta02.txt b/fragment/fragment-testing/api/restricted_1.6.0-beta02.txt
new file mode 100644
index 0000000..d5c260e
--- /dev/null
+++ b/fragment/fragment-testing/api/restricted_1.6.0-beta02.txt
@@ -0,0 +1,60 @@
+// Signature format: 4.0
+package androidx.fragment.app.testing {
+
+  public final class FragmentScenario<F extends androidx.fragment.app.Fragment> implements java.io.Closeable {
+    method public void close();
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass);
+    method public androidx.fragment.app.testing.FragmentScenario<F> moveToState(androidx.lifecycle.Lifecycle.State newState);
+    method public androidx.fragment.app.testing.FragmentScenario<F> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F> action);
+    method public androidx.fragment.app.testing.FragmentScenario<F> recreate();
+    field public static final androidx.fragment.app.testing.FragmentScenario.Companion Companion;
+  }
+
+  public static final class FragmentScenario.Companion {
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launch(Class<F> fragmentClass);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, android.os.Bundle? fragmentArgs, @StyleRes int themeResId, androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass, optional android.os.Bundle? fragmentArgs);
+    method public <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchInContainer(Class<F> fragmentClass);
+  }
+
+  public static fun interface FragmentScenario.FragmentAction<F extends androidx.fragment.app.Fragment> {
+    method public void perform(F fragment);
+  }
+
+  public final class FragmentScenarioKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.fragment.app.FragmentFactory? factory);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragment(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.fragment.app.FragmentFactory? factory);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, optional androidx.fragment.app.FragmentFactory? factory);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F> launchFragmentInContainer(optional android.os.Bundle? fragmentArgs, optional @StyleRes int themeResId, optional androidx.lifecycle.Lifecycle.State initialState, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, T> T withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
+  }
+
+}
+
diff --git a/fragment/fragment/api/1.6.0-beta02.txt b/fragment/fragment/api/1.6.0-beta02.txt
new file mode 100644
index 0000000..4d44df2
--- /dev/null
+++ b/fragment/fragment/api/1.6.0-beta02.txt
@@ -0,0 +1,554 @@
+// Signature format: 4.0
+package androidx.fragment.app {
+
+  public class DialogFragment extends androidx.fragment.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+    ctor public DialogFragment();
+    ctor public DialogFragment(@LayoutRes int);
+    method public void dismiss();
+    method public void dismissAllowingStateLoss();
+    method @MainThread public void dismissNow();
+    method public android.app.Dialog? getDialog();
+    method public boolean getShowsDialog();
+    method @StyleRes public int getTheme();
+    method public boolean isCancelable();
+    method public void onCancel(android.content.DialogInterface);
+    method @MainThread public android.app.Dialog onCreateDialog(android.os.Bundle?);
+    method @CallSuper public void onDismiss(android.content.DialogInterface);
+    method public final androidx.activity.ComponentDialog requireComponentDialog();
+    method public final android.app.Dialog requireDialog();
+    method public void setCancelable(boolean);
+    method public void setShowsDialog(boolean);
+    method public void setStyle(int, @StyleRes int);
+    method public void show(androidx.fragment.app.FragmentManager, String?);
+    method public int show(androidx.fragment.app.FragmentTransaction, String?);
+    method public void showNow(androidx.fragment.app.FragmentManager, String?);
+    field public static final int STYLE_NORMAL = 0; // 0x0
+    field public static final int STYLE_NO_FRAME = 2; // 0x2
+    field public static final int STYLE_NO_INPUT = 3; // 0x3
+    field public static final int STYLE_NO_TITLE = 1; // 0x1
+  }
+
+  public class Fragment implements androidx.activity.result.ActivityResultCaller android.content.ComponentCallbacks androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner android.view.View.OnCreateContextMenuListener androidx.lifecycle.ViewModelStoreOwner {
+    ctor public Fragment();
+    ctor @ContentView public Fragment(@LayoutRes int);
+    method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public final boolean equals(Object?);
+    method public final androidx.fragment.app.FragmentActivity? getActivity();
+    method public boolean getAllowEnterTransitionOverlap();
+    method public boolean getAllowReturnTransitionOverlap();
+    method public final android.os.Bundle? getArguments();
+    method public final androidx.fragment.app.FragmentManager getChildFragmentManager();
+    method public android.content.Context? getContext();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public Object? getEnterTransition();
+    method public Object? getExitTransition();
+    method @Deprecated public final androidx.fragment.app.FragmentManager? getFragmentManager();
+    method public final Object? getHost();
+    method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @Deprecated public androidx.loader.app.LoaderManager getLoaderManager();
+    method public final androidx.fragment.app.Fragment? getParentFragment();
+    method public final androidx.fragment.app.FragmentManager getParentFragmentManager();
+    method public Object? getReenterTransition();
+    method public final android.content.res.Resources getResources();
+    method @Deprecated public final boolean getRetainInstance();
+    method public Object? getReturnTransition();
+    method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public Object? getSharedElementEnterTransition();
+    method public Object? getSharedElementReturnTransition();
+    method public final String getString(@StringRes int);
+    method public final String getString(@StringRes int, java.lang.Object!...);
+    method public final String? getTag();
+    method @Deprecated public final androidx.fragment.app.Fragment? getTargetFragment();
+    method @Deprecated public final int getTargetRequestCode();
+    method public final CharSequence getText(@StringRes int);
+    method @Deprecated public boolean getUserVisibleHint();
+    method public android.view.View? getView();
+    method @MainThread public androidx.lifecycle.LifecycleOwner getViewLifecycleOwner();
+    method public androidx.lifecycle.LiveData<androidx.lifecycle.LifecycleOwner!> getViewLifecycleOwnerLiveData();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    method public final int hashCode();
+    method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String);
+    method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+    method public final boolean isAdded();
+    method public final boolean isDetached();
+    method public final boolean isHidden();
+    method public final boolean isInLayout();
+    method public final boolean isRemoving();
+    method public final boolean isResumed();
+    method public final boolean isStateSaved();
+    method public final boolean isVisible();
+    method @Deprecated @CallSuper @MainThread public void onActivityCreated(android.os.Bundle?);
+    method @Deprecated public void onActivityResult(int, int, android.content.Intent?);
+    method @CallSuper @MainThread public void onAttach(android.content.Context);
+    method @Deprecated @CallSuper @MainThread public void onAttach(android.app.Activity);
+    method @Deprecated @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+    method @CallSuper public void onConfigurationChanged(android.content.res.Configuration);
+    method @MainThread public boolean onContextItemSelected(android.view.MenuItem);
+    method @CallSuper @MainThread public void onCreate(android.os.Bundle?);
+    method @MainThread public android.view.animation.Animation? onCreateAnimation(int, boolean, int);
+    method @MainThread public android.animation.Animator? onCreateAnimator(int, boolean, int);
+    method @MainThread public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo?);
+    method @Deprecated @MainThread public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method @MainThread public android.view.View? onCreateView(android.view.LayoutInflater, android.view.ViewGroup?, android.os.Bundle?);
+    method @CallSuper @MainThread public void onDestroy();
+    method @Deprecated @MainThread public void onDestroyOptionsMenu();
+    method @CallSuper @MainThread public void onDestroyView();
+    method @CallSuper @MainThread public void onDetach();
+    method public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle?);
+    method @MainThread public void onHiddenChanged(boolean);
+    method @CallSuper @UiThread public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle?);
+    method @Deprecated @CallSuper @UiThread public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle?);
+    method @CallSuper @MainThread public void onLowMemory();
+    method public void onMultiWindowModeChanged(boolean);
+    method @Deprecated @MainThread public boolean onOptionsItemSelected(android.view.MenuItem);
+    method @Deprecated @MainThread public void onOptionsMenuClosed(android.view.Menu);
+    method @CallSuper @MainThread public void onPause();
+    method public void onPictureInPictureModeChanged(boolean);
+    method @Deprecated @MainThread public void onPrepareOptionsMenu(android.view.Menu);
+    method @MainThread public void onPrimaryNavigationFragmentChanged(boolean);
+    method @Deprecated public void onRequestPermissionsResult(int, String![], int[]);
+    method @CallSuper @MainThread public void onResume();
+    method @MainThread public void onSaveInstanceState(android.os.Bundle);
+    method @CallSuper @MainThread public void onStart();
+    method @CallSuper @MainThread public void onStop();
+    method @MainThread public void onViewCreated(android.view.View, android.os.Bundle?);
+    method @CallSuper @MainThread public void onViewStateRestored(android.os.Bundle?);
+    method public void postponeEnterTransition();
+    method public final void postponeEnterTransition(long, java.util.concurrent.TimeUnit);
+    method @MainThread public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+    method @MainThread public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+    method public void registerForContextMenu(android.view.View);
+    method @Deprecated public final void requestPermissions(String![], int);
+    method public final androidx.fragment.app.FragmentActivity requireActivity();
+    method public final android.os.Bundle requireArguments();
+    method public final android.content.Context requireContext();
+    method @Deprecated public final androidx.fragment.app.FragmentManager requireFragmentManager();
+    method public final Object requireHost();
+    method public final androidx.fragment.app.Fragment requireParentFragment();
+    method public final android.view.View requireView();
+    method public void setAllowEnterTransitionOverlap(boolean);
+    method public void setAllowReturnTransitionOverlap(boolean);
+    method public void setArguments(android.os.Bundle?);
+    method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setEnterTransition(Object?);
+    method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setExitTransition(Object?);
+    method @Deprecated public void setHasOptionsMenu(boolean);
+    method public void setInitialSavedState(androidx.fragment.app.Fragment.SavedState?);
+    method public void setMenuVisibility(boolean);
+    method public void setReenterTransition(Object?);
+    method @Deprecated public void setRetainInstance(boolean);
+    method public void setReturnTransition(Object?);
+    method public void setSharedElementEnterTransition(Object?);
+    method public void setSharedElementReturnTransition(Object?);
+    method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
+    method @Deprecated public void setUserVisibleHint(boolean);
+    method public boolean shouldShowRequestPermissionRationale(String);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle?);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startPostponedEnterTransition();
+    method public void unregisterForContextMenu(android.view.View);
+  }
+
+  public static class Fragment.InstantiationException extends java.lang.RuntimeException {
+    ctor public Fragment.InstantiationException(String, Exception?);
+  }
+
+  public static class Fragment.SavedState implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<androidx.fragment.app.Fragment.SavedState!> CREATOR;
+  }
+
+  public class FragmentActivity extends androidx.activity.ComponentActivity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback androidx.lifecycle.LifecycleOwner {
+    ctor public FragmentActivity();
+    ctor @ContentView public FragmentActivity(@LayoutRes int);
+    method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+    method @Deprecated public androidx.loader.app.LoaderManager getSupportLoaderManager();
+    method @Deprecated @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+    method protected void onResumeFragments();
+    method public void onStateNotSaved();
+    method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void supportFinishAfterTransition();
+    method @Deprecated public void supportInvalidateOptionsMenu();
+    method public void supportPostponeEnterTransition();
+    method public void supportStartPostponedEnterTransition();
+    method @Deprecated public final void validateRequestPermissionsRequestCode(int);
+  }
+
+  public abstract class FragmentContainer {
+    ctor public FragmentContainer();
+    method @Deprecated public androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+    method public abstract android.view.View? onFindViewById(@IdRes int);
+    method public abstract boolean onHasView();
+  }
+
+  public final class FragmentContainerView extends android.widget.FrameLayout {
+    ctor public FragmentContainerView(android.content.Context context);
+    ctor public FragmentContainerView(android.content.Context context, android.util.AttributeSet? attrs, optional int defStyleAttr);
+    ctor public FragmentContainerView(android.content.Context context, android.util.AttributeSet? attrs);
+    method public <F extends androidx.fragment.app.Fragment> F getFragment();
+  }
+
+  public class FragmentController {
+    method public void attachHost(androidx.fragment.app.Fragment?);
+    method public static androidx.fragment.app.FragmentController createController(androidx.fragment.app.FragmentHostCallback<?>);
+    method public void dispatchActivityCreated();
+    method @Deprecated public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public boolean dispatchContextItemSelected(android.view.MenuItem);
+    method public void dispatchCreate();
+    method @Deprecated public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public void dispatchDestroy();
+    method public void dispatchDestroyView();
+    method @Deprecated public void dispatchLowMemory();
+    method @Deprecated public void dispatchMultiWindowModeChanged(boolean);
+    method @Deprecated public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+    method @Deprecated public void dispatchOptionsMenuClosed(android.view.Menu);
+    method public void dispatchPause();
+    method @Deprecated public void dispatchPictureInPictureModeChanged(boolean);
+    method @Deprecated public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+    method @Deprecated public void dispatchReallyStop();
+    method public void dispatchResume();
+    method public void dispatchStart();
+    method public void dispatchStop();
+    method @Deprecated public void doLoaderDestroy();
+    method @Deprecated public void doLoaderRetain();
+    method @Deprecated public void doLoaderStart();
+    method @Deprecated public void doLoaderStop(boolean);
+    method @Deprecated public void dumpLoaders(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public boolean execPendingActions();
+    method public androidx.fragment.app.Fragment? findFragmentByWho(String);
+    method public java.util.List<androidx.fragment.app.Fragment!> getActiveFragments(java.util.List<androidx.fragment.app.Fragment!>!);
+    method public int getActiveFragmentsCount();
+    method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+    method @Deprecated public androidx.loader.app.LoaderManager! getSupportLoaderManager();
+    method public void noteStateNotSaved();
+    method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
+    method @Deprecated public void reportLoaderStart();
+    method @Deprecated public void restoreAllState(android.os.Parcelable?, java.util.List<androidx.fragment.app.Fragment!>?);
+    method @Deprecated public void restoreAllState(android.os.Parcelable?, androidx.fragment.app.FragmentManagerNonConfig?);
+    method @Deprecated public void restoreLoaderNonConfig(androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>!);
+    method @Deprecated public void restoreSaveState(android.os.Parcelable?);
+    method @Deprecated public androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>? retainLoaderNonConfig();
+    method @Deprecated public androidx.fragment.app.FragmentManagerNonConfig? retainNestedNonConfig();
+    method @Deprecated public java.util.List<androidx.fragment.app.Fragment!>? retainNonConfig();
+    method @Deprecated public android.os.Parcelable? saveAllState();
+  }
+
+  public class FragmentFactory {
+    ctor public FragmentFactory();
+    method public androidx.fragment.app.Fragment instantiate(ClassLoader, String);
+    method public static Class<? extends androidx.fragment.app.Fragment> loadFragmentClass(ClassLoader, String);
+  }
+
+  public abstract class FragmentHostCallback<E> extends androidx.fragment.app.FragmentContainer {
+    ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+    method public void onDump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public android.view.View? onFindViewById(int);
+    method public abstract E? onGetHost();
+    method public android.view.LayoutInflater onGetLayoutInflater();
+    method public int onGetWindowAnimations();
+    method public boolean onHasView();
+    method public boolean onHasWindowAnimations();
+    method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
+    method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
+    method public boolean onShouldShowRequestPermissionRationale(String);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void onSupportInvalidateOptionsMenu();
+  }
+
+  public abstract class FragmentManager implements androidx.fragment.app.FragmentResultOwner {
+    ctor public FragmentManager();
+    method public void addFragmentOnAttachListener(androidx.fragment.app.FragmentOnAttachListener);
+    method public void addOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+    method public androidx.fragment.app.FragmentTransaction beginTransaction();
+    method public void clearBackStack(String);
+    method public final void clearFragmentResult(String);
+    method public final void clearFragmentResultListener(String);
+    method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method @Deprecated public static void enableDebugLogging(boolean);
+    method @MainThread public boolean executePendingTransactions();
+    method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+    method public androidx.fragment.app.Fragment? findFragmentById(@IdRes int);
+    method public androidx.fragment.app.Fragment? findFragmentByTag(String?);
+    method public androidx.fragment.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+    method public int getBackStackEntryCount();
+    method public androidx.fragment.app.Fragment? getFragment(android.os.Bundle, String);
+    method public androidx.fragment.app.FragmentFactory getFragmentFactory();
+    method public java.util.List<androidx.fragment.app.Fragment!> getFragments();
+    method public androidx.fragment.app.Fragment? getPrimaryNavigationFragment();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy? getStrictModePolicy();
+    method public boolean isDestroyed();
+    method public boolean isStateSaved();
+    method public void popBackStack();
+    method public void popBackStack(String?, int);
+    method public void popBackStack(int, int);
+    method @MainThread public boolean popBackStackImmediate();
+    method @MainThread public boolean popBackStackImmediate(String?, int);
+    method public boolean popBackStackImmediate(int, int);
+    method public void putFragment(android.os.Bundle, String, androidx.fragment.app.Fragment);
+    method public void registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks, boolean);
+    method public void removeFragmentOnAttachListener(androidx.fragment.app.FragmentOnAttachListener);
+    method public void removeOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+    method public void restoreBackStack(String);
+    method public void saveBackStack(String);
+    method public androidx.fragment.app.Fragment.SavedState? saveFragmentInstanceState(androidx.fragment.app.Fragment);
+    method public void setFragmentFactory(androidx.fragment.app.FragmentFactory);
+    method public final void setFragmentResult(String, android.os.Bundle);
+    method public final void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+    method public void setStrictModePolicy(androidx.fragment.app.strictmode.FragmentStrictMode.Policy?);
+    method public void unregisterFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks);
+    field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+  }
+
+  public static interface FragmentManager.BackStackEntry {
+    method @Deprecated public CharSequence? getBreadCrumbShortTitle();
+    method @Deprecated @StringRes public int getBreadCrumbShortTitleRes();
+    method @Deprecated public CharSequence? getBreadCrumbTitle();
+    method @Deprecated @StringRes public int getBreadCrumbTitleRes();
+    method public int getId();
+    method public String? getName();
+  }
+
+  public abstract static class FragmentManager.FragmentLifecycleCallbacks {
+    ctor public FragmentManager.FragmentLifecycleCallbacks();
+    method @Deprecated public void onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+    method public void onFragmentCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentDetached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentPaused(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentPreAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+    method public void onFragmentPreCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentResumed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentSaveInstanceState(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle);
+    method public void onFragmentStarted(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentStopped(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentViewCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.view.View, android.os.Bundle?);
+    method public void onFragmentViewDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+  }
+
+  public static interface FragmentManager.OnBackStackChangedListener {
+    method @MainThread public default void onBackStackChangeCommitted(androidx.fragment.app.Fragment, boolean);
+    method @MainThread public default void onBackStackChangeStarted(androidx.fragment.app.Fragment, boolean);
+    method @MainThread public void onBackStackChanged();
+  }
+
+  @Deprecated public class FragmentManagerNonConfig {
+  }
+
+  public interface FragmentOnAttachListener {
+    method @MainThread public void onAttachFragment(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+  }
+
+  @Deprecated public abstract class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+    ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager);
+    ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager, int);
+    method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+    method @Deprecated public long getItemId(int);
+    method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+    field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+    field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+  }
+
+  public interface FragmentResultListener {
+    method public void onFragmentResult(String, android.os.Bundle);
+  }
+
+  public interface FragmentResultOwner {
+    method public void clearFragmentResult(String);
+    method public void clearFragmentResultListener(String);
+    method public void setFragmentResult(String, android.os.Bundle);
+    method public void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+  }
+
+  @Deprecated public abstract class FragmentStatePagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+    ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager);
+    ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager, int);
+    method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+    method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+    field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+    field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+  }
+
+  @Deprecated public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+    ctor @Deprecated public FragmentTabHost(android.content.Context);
+    ctor @Deprecated public FragmentTabHost(android.content.Context, android.util.AttributeSet?);
+    method @Deprecated public void addTab(android.widget.TabHost.TabSpec, Class<?>, android.os.Bundle?);
+    method @Deprecated public void onTabChanged(String?);
+    method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager);
+    method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager, int);
+  }
+
+  public abstract class FragmentTransaction {
+    ctor @Deprecated public FragmentTransaction();
+    method public final androidx.fragment.app.FragmentTransaction add(Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.Fragment, String?);
+    method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+    method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment, String?);
+    method public androidx.fragment.app.FragmentTransaction addSharedElement(android.view.View, String);
+    method public androidx.fragment.app.FragmentTransaction addToBackStack(String?);
+    method public androidx.fragment.app.FragmentTransaction attach(androidx.fragment.app.Fragment);
+    method public abstract int commit();
+    method public abstract int commitAllowingStateLoss();
+    method @MainThread public abstract void commitNow();
+    method @MainThread public abstract void commitNowAllowingStateLoss();
+    method public androidx.fragment.app.FragmentTransaction detach(androidx.fragment.app.Fragment);
+    method public androidx.fragment.app.FragmentTransaction disallowAddToBackStack();
+    method public androidx.fragment.app.FragmentTransaction hide(androidx.fragment.app.Fragment);
+    method public boolean isAddToBackStackAllowed();
+    method public boolean isEmpty();
+    method public androidx.fragment.app.FragmentTransaction remove(androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+    method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment, String?);
+    method public androidx.fragment.app.FragmentTransaction runOnCommit(Runnable);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setAllowOptimization(boolean);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(@StringRes int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(CharSequence?);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(@StringRes int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(CharSequence?);
+    method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+    method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+    method public androidx.fragment.app.FragmentTransaction setMaxLifecycle(androidx.fragment.app.Fragment, androidx.lifecycle.Lifecycle.State);
+    method public androidx.fragment.app.FragmentTransaction setPrimaryNavigationFragment(androidx.fragment.app.Fragment?);
+    method public androidx.fragment.app.FragmentTransaction setReorderingAllowed(boolean);
+    method public androidx.fragment.app.FragmentTransaction setTransition(int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setTransitionStyle(@StyleRes int);
+    method public androidx.fragment.app.FragmentTransaction show(androidx.fragment.app.Fragment);
+    field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+    field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+    field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+    field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+    field public static final int TRANSIT_FRAGMENT_MATCH_ACTIVITY_CLOSE = 8197; // 0x2005
+    field public static final int TRANSIT_FRAGMENT_MATCH_ACTIVITY_OPEN = 4100; // 0x1004
+    field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+    field public static final int TRANSIT_NONE = 0; // 0x0
+    field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+  }
+
+  public class ListFragment extends androidx.fragment.app.Fragment {
+    ctor public ListFragment();
+    method public android.widget.ListAdapter? getListAdapter();
+    method public android.widget.ListView getListView();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+    method public final android.widget.ListAdapter requireListAdapter();
+    method public void setEmptyText(CharSequence?);
+    method public void setListAdapter(android.widget.ListAdapter?);
+    method public void setListShown(boolean);
+    method public void setListShownNoAnimation(boolean);
+    method public void setSelection(int);
+  }
+
+}
+
+package androidx.fragment.app.strictmode {
+
+  public final class FragmentReuseViolation extends androidx.fragment.app.strictmode.Violation {
+    method public String getPreviousFragmentId();
+    property public final String previousFragmentId;
+  }
+
+  public final class FragmentStrictMode {
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy getDefaultPolicy();
+    method @VisibleForTesting public void onPolicyViolation(androidx.fragment.app.strictmode.Violation violation);
+    method public void setDefaultPolicy(androidx.fragment.app.strictmode.FragmentStrictMode.Policy);
+    property public final androidx.fragment.app.strictmode.FragmentStrictMode.Policy defaultPolicy;
+    field public static final androidx.fragment.app.strictmode.FragmentStrictMode INSTANCE;
+  }
+
+  public static fun interface FragmentStrictMode.OnViolationListener {
+    method public void onViolation(androidx.fragment.app.strictmode.Violation violation);
+  }
+
+  public static final class FragmentStrictMode.Policy {
+    field public static final androidx.fragment.app.strictmode.FragmentStrictMode.Policy LAX;
+  }
+
+  public static final class FragmentStrictMode.Policy.Builder {
+    ctor public FragmentStrictMode.Policy.Builder();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(Class<? extends androidx.fragment.app.Fragment> fragmentClass, Class<? extends androidx.fragment.app.strictmode.Violation> violationClass);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(String fragmentClass, Class<? extends androidx.fragment.app.strictmode.Violation> violationClass);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy build();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentReuse();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentTagUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectRetainInstanceUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectSetUserVisibleHint();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectTargetFragmentUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectWrongFragmentContainer();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectWrongNestedHierarchy();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyDeath();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyListener(androidx.fragment.app.strictmode.FragmentStrictMode.OnViolationListener listener);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyLog();
+  }
+
+  public final class FragmentTagUsageViolation extends androidx.fragment.app.strictmode.Violation {
+    method public android.view.ViewGroup? getParentContainer();
+    property public final android.view.ViewGroup? parentContainer;
+  }
+
+  public final class GetRetainInstanceUsageViolation extends androidx.fragment.app.strictmode.RetainInstanceUsageViolation {
+  }
+
+  public final class GetTargetFragmentRequestCodeUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+  }
+
+  public final class GetTargetFragmentUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+  }
+
+  public abstract class RetainInstanceUsageViolation extends androidx.fragment.app.strictmode.Violation {
+  }
+
+  public final class SetRetainInstanceUsageViolation extends androidx.fragment.app.strictmode.RetainInstanceUsageViolation {
+  }
+
+  public final class SetTargetFragmentUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+    method public int getRequestCode();
+    method public androidx.fragment.app.Fragment getTargetFragment();
+    property public final int requestCode;
+    property public final androidx.fragment.app.Fragment targetFragment;
+  }
+
+  public final class SetUserVisibleHintViolation extends androidx.fragment.app.strictmode.Violation {
+    method public boolean isVisibleToUser();
+    property public final boolean isVisibleToUser;
+  }
+
+  public abstract class TargetFragmentUsageViolation extends androidx.fragment.app.strictmode.Violation {
+  }
+
+  public abstract class Violation extends java.lang.RuntimeException {
+    method public final androidx.fragment.app.Fragment getFragment();
+    property public final androidx.fragment.app.Fragment fragment;
+  }
+
+  public final class WrongFragmentContainerViolation extends androidx.fragment.app.strictmode.Violation {
+    method public android.view.ViewGroup getContainer();
+    property public final android.view.ViewGroup container;
+  }
+
+  public final class WrongNestedHierarchyViolation extends androidx.fragment.app.strictmode.Violation {
+    method public int getContainerId();
+    method public androidx.fragment.app.Fragment getExpectedParentFragment();
+    property public final int containerId;
+    property public final androidx.fragment.app.Fragment expectedParentFragment;
+  }
+
+}
+
diff --git a/fragment/fragment/api/public_plus_experimental_1.6.0-beta02.txt b/fragment/fragment/api/public_plus_experimental_1.6.0-beta02.txt
new file mode 100644
index 0000000..4d44df2
--- /dev/null
+++ b/fragment/fragment/api/public_plus_experimental_1.6.0-beta02.txt
@@ -0,0 +1,554 @@
+// Signature format: 4.0
+package androidx.fragment.app {
+
+  public class DialogFragment extends androidx.fragment.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+    ctor public DialogFragment();
+    ctor public DialogFragment(@LayoutRes int);
+    method public void dismiss();
+    method public void dismissAllowingStateLoss();
+    method @MainThread public void dismissNow();
+    method public android.app.Dialog? getDialog();
+    method public boolean getShowsDialog();
+    method @StyleRes public int getTheme();
+    method public boolean isCancelable();
+    method public void onCancel(android.content.DialogInterface);
+    method @MainThread public android.app.Dialog onCreateDialog(android.os.Bundle?);
+    method @CallSuper public void onDismiss(android.content.DialogInterface);
+    method public final androidx.activity.ComponentDialog requireComponentDialog();
+    method public final android.app.Dialog requireDialog();
+    method public void setCancelable(boolean);
+    method public void setShowsDialog(boolean);
+    method public void setStyle(int, @StyleRes int);
+    method public void show(androidx.fragment.app.FragmentManager, String?);
+    method public int show(androidx.fragment.app.FragmentTransaction, String?);
+    method public void showNow(androidx.fragment.app.FragmentManager, String?);
+    field public static final int STYLE_NORMAL = 0; // 0x0
+    field public static final int STYLE_NO_FRAME = 2; // 0x2
+    field public static final int STYLE_NO_INPUT = 3; // 0x3
+    field public static final int STYLE_NO_TITLE = 1; // 0x1
+  }
+
+  public class Fragment implements androidx.activity.result.ActivityResultCaller android.content.ComponentCallbacks androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner android.view.View.OnCreateContextMenuListener androidx.lifecycle.ViewModelStoreOwner {
+    ctor public Fragment();
+    ctor @ContentView public Fragment(@LayoutRes int);
+    method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public final boolean equals(Object?);
+    method public final androidx.fragment.app.FragmentActivity? getActivity();
+    method public boolean getAllowEnterTransitionOverlap();
+    method public boolean getAllowReturnTransitionOverlap();
+    method public final android.os.Bundle? getArguments();
+    method public final androidx.fragment.app.FragmentManager getChildFragmentManager();
+    method public android.content.Context? getContext();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public Object? getEnterTransition();
+    method public Object? getExitTransition();
+    method @Deprecated public final androidx.fragment.app.FragmentManager? getFragmentManager();
+    method public final Object? getHost();
+    method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @Deprecated public androidx.loader.app.LoaderManager getLoaderManager();
+    method public final androidx.fragment.app.Fragment? getParentFragment();
+    method public final androidx.fragment.app.FragmentManager getParentFragmentManager();
+    method public Object? getReenterTransition();
+    method public final android.content.res.Resources getResources();
+    method @Deprecated public final boolean getRetainInstance();
+    method public Object? getReturnTransition();
+    method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public Object? getSharedElementEnterTransition();
+    method public Object? getSharedElementReturnTransition();
+    method public final String getString(@StringRes int);
+    method public final String getString(@StringRes int, java.lang.Object!...);
+    method public final String? getTag();
+    method @Deprecated public final androidx.fragment.app.Fragment? getTargetFragment();
+    method @Deprecated public final int getTargetRequestCode();
+    method public final CharSequence getText(@StringRes int);
+    method @Deprecated public boolean getUserVisibleHint();
+    method public android.view.View? getView();
+    method @MainThread public androidx.lifecycle.LifecycleOwner getViewLifecycleOwner();
+    method public androidx.lifecycle.LiveData<androidx.lifecycle.LifecycleOwner!> getViewLifecycleOwnerLiveData();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    method public final int hashCode();
+    method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String);
+    method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+    method public final boolean isAdded();
+    method public final boolean isDetached();
+    method public final boolean isHidden();
+    method public final boolean isInLayout();
+    method public final boolean isRemoving();
+    method public final boolean isResumed();
+    method public final boolean isStateSaved();
+    method public final boolean isVisible();
+    method @Deprecated @CallSuper @MainThread public void onActivityCreated(android.os.Bundle?);
+    method @Deprecated public void onActivityResult(int, int, android.content.Intent?);
+    method @CallSuper @MainThread public void onAttach(android.content.Context);
+    method @Deprecated @CallSuper @MainThread public void onAttach(android.app.Activity);
+    method @Deprecated @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+    method @CallSuper public void onConfigurationChanged(android.content.res.Configuration);
+    method @MainThread public boolean onContextItemSelected(android.view.MenuItem);
+    method @CallSuper @MainThread public void onCreate(android.os.Bundle?);
+    method @MainThread public android.view.animation.Animation? onCreateAnimation(int, boolean, int);
+    method @MainThread public android.animation.Animator? onCreateAnimator(int, boolean, int);
+    method @MainThread public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo?);
+    method @Deprecated @MainThread public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method @MainThread public android.view.View? onCreateView(android.view.LayoutInflater, android.view.ViewGroup?, android.os.Bundle?);
+    method @CallSuper @MainThread public void onDestroy();
+    method @Deprecated @MainThread public void onDestroyOptionsMenu();
+    method @CallSuper @MainThread public void onDestroyView();
+    method @CallSuper @MainThread public void onDetach();
+    method public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle?);
+    method @MainThread public void onHiddenChanged(boolean);
+    method @CallSuper @UiThread public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle?);
+    method @Deprecated @CallSuper @UiThread public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle?);
+    method @CallSuper @MainThread public void onLowMemory();
+    method public void onMultiWindowModeChanged(boolean);
+    method @Deprecated @MainThread public boolean onOptionsItemSelected(android.view.MenuItem);
+    method @Deprecated @MainThread public void onOptionsMenuClosed(android.view.Menu);
+    method @CallSuper @MainThread public void onPause();
+    method public void onPictureInPictureModeChanged(boolean);
+    method @Deprecated @MainThread public void onPrepareOptionsMenu(android.view.Menu);
+    method @MainThread public void onPrimaryNavigationFragmentChanged(boolean);
+    method @Deprecated public void onRequestPermissionsResult(int, String![], int[]);
+    method @CallSuper @MainThread public void onResume();
+    method @MainThread public void onSaveInstanceState(android.os.Bundle);
+    method @CallSuper @MainThread public void onStart();
+    method @CallSuper @MainThread public void onStop();
+    method @MainThread public void onViewCreated(android.view.View, android.os.Bundle?);
+    method @CallSuper @MainThread public void onViewStateRestored(android.os.Bundle?);
+    method public void postponeEnterTransition();
+    method public final void postponeEnterTransition(long, java.util.concurrent.TimeUnit);
+    method @MainThread public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+    method @MainThread public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+    method public void registerForContextMenu(android.view.View);
+    method @Deprecated public final void requestPermissions(String![], int);
+    method public final androidx.fragment.app.FragmentActivity requireActivity();
+    method public final android.os.Bundle requireArguments();
+    method public final android.content.Context requireContext();
+    method @Deprecated public final androidx.fragment.app.FragmentManager requireFragmentManager();
+    method public final Object requireHost();
+    method public final androidx.fragment.app.Fragment requireParentFragment();
+    method public final android.view.View requireView();
+    method public void setAllowEnterTransitionOverlap(boolean);
+    method public void setAllowReturnTransitionOverlap(boolean);
+    method public void setArguments(android.os.Bundle?);
+    method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setEnterTransition(Object?);
+    method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setExitTransition(Object?);
+    method @Deprecated public void setHasOptionsMenu(boolean);
+    method public void setInitialSavedState(androidx.fragment.app.Fragment.SavedState?);
+    method public void setMenuVisibility(boolean);
+    method public void setReenterTransition(Object?);
+    method @Deprecated public void setRetainInstance(boolean);
+    method public void setReturnTransition(Object?);
+    method public void setSharedElementEnterTransition(Object?);
+    method public void setSharedElementReturnTransition(Object?);
+    method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
+    method @Deprecated public void setUserVisibleHint(boolean);
+    method public boolean shouldShowRequestPermissionRationale(String);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle?);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startPostponedEnterTransition();
+    method public void unregisterForContextMenu(android.view.View);
+  }
+
+  public static class Fragment.InstantiationException extends java.lang.RuntimeException {
+    ctor public Fragment.InstantiationException(String, Exception?);
+  }
+
+  public static class Fragment.SavedState implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<androidx.fragment.app.Fragment.SavedState!> CREATOR;
+  }
+
+  public class FragmentActivity extends androidx.activity.ComponentActivity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback androidx.lifecycle.LifecycleOwner {
+    ctor public FragmentActivity();
+    ctor @ContentView public FragmentActivity(@LayoutRes int);
+    method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+    method @Deprecated public androidx.loader.app.LoaderManager getSupportLoaderManager();
+    method @Deprecated @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+    method protected void onResumeFragments();
+    method public void onStateNotSaved();
+    method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void supportFinishAfterTransition();
+    method @Deprecated public void supportInvalidateOptionsMenu();
+    method public void supportPostponeEnterTransition();
+    method public void supportStartPostponedEnterTransition();
+    method @Deprecated public final void validateRequestPermissionsRequestCode(int);
+  }
+
+  public abstract class FragmentContainer {
+    ctor public FragmentContainer();
+    method @Deprecated public androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+    method public abstract android.view.View? onFindViewById(@IdRes int);
+    method public abstract boolean onHasView();
+  }
+
+  public final class FragmentContainerView extends android.widget.FrameLayout {
+    ctor public FragmentContainerView(android.content.Context context);
+    ctor public FragmentContainerView(android.content.Context context, android.util.AttributeSet? attrs, optional int defStyleAttr);
+    ctor public FragmentContainerView(android.content.Context context, android.util.AttributeSet? attrs);
+    method public <F extends androidx.fragment.app.Fragment> F getFragment();
+  }
+
+  public class FragmentController {
+    method public void attachHost(androidx.fragment.app.Fragment?);
+    method public static androidx.fragment.app.FragmentController createController(androidx.fragment.app.FragmentHostCallback<?>);
+    method public void dispatchActivityCreated();
+    method @Deprecated public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public boolean dispatchContextItemSelected(android.view.MenuItem);
+    method public void dispatchCreate();
+    method @Deprecated public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public void dispatchDestroy();
+    method public void dispatchDestroyView();
+    method @Deprecated public void dispatchLowMemory();
+    method @Deprecated public void dispatchMultiWindowModeChanged(boolean);
+    method @Deprecated public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+    method @Deprecated public void dispatchOptionsMenuClosed(android.view.Menu);
+    method public void dispatchPause();
+    method @Deprecated public void dispatchPictureInPictureModeChanged(boolean);
+    method @Deprecated public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+    method @Deprecated public void dispatchReallyStop();
+    method public void dispatchResume();
+    method public void dispatchStart();
+    method public void dispatchStop();
+    method @Deprecated public void doLoaderDestroy();
+    method @Deprecated public void doLoaderRetain();
+    method @Deprecated public void doLoaderStart();
+    method @Deprecated public void doLoaderStop(boolean);
+    method @Deprecated public void dumpLoaders(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public boolean execPendingActions();
+    method public androidx.fragment.app.Fragment? findFragmentByWho(String);
+    method public java.util.List<androidx.fragment.app.Fragment!> getActiveFragments(java.util.List<androidx.fragment.app.Fragment!>!);
+    method public int getActiveFragmentsCount();
+    method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+    method @Deprecated public androidx.loader.app.LoaderManager! getSupportLoaderManager();
+    method public void noteStateNotSaved();
+    method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
+    method @Deprecated public void reportLoaderStart();
+    method @Deprecated public void restoreAllState(android.os.Parcelable?, java.util.List<androidx.fragment.app.Fragment!>?);
+    method @Deprecated public void restoreAllState(android.os.Parcelable?, androidx.fragment.app.FragmentManagerNonConfig?);
+    method @Deprecated public void restoreLoaderNonConfig(androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>!);
+    method @Deprecated public void restoreSaveState(android.os.Parcelable?);
+    method @Deprecated public androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>? retainLoaderNonConfig();
+    method @Deprecated public androidx.fragment.app.FragmentManagerNonConfig? retainNestedNonConfig();
+    method @Deprecated public java.util.List<androidx.fragment.app.Fragment!>? retainNonConfig();
+    method @Deprecated public android.os.Parcelable? saveAllState();
+  }
+
+  public class FragmentFactory {
+    ctor public FragmentFactory();
+    method public androidx.fragment.app.Fragment instantiate(ClassLoader, String);
+    method public static Class<? extends androidx.fragment.app.Fragment> loadFragmentClass(ClassLoader, String);
+  }
+
+  public abstract class FragmentHostCallback<E> extends androidx.fragment.app.FragmentContainer {
+    ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+    method public void onDump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public android.view.View? onFindViewById(int);
+    method public abstract E? onGetHost();
+    method public android.view.LayoutInflater onGetLayoutInflater();
+    method public int onGetWindowAnimations();
+    method public boolean onHasView();
+    method public boolean onHasWindowAnimations();
+    method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
+    method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
+    method public boolean onShouldShowRequestPermissionRationale(String);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void onSupportInvalidateOptionsMenu();
+  }
+
+  public abstract class FragmentManager implements androidx.fragment.app.FragmentResultOwner {
+    ctor public FragmentManager();
+    method public void addFragmentOnAttachListener(androidx.fragment.app.FragmentOnAttachListener);
+    method public void addOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+    method public androidx.fragment.app.FragmentTransaction beginTransaction();
+    method public void clearBackStack(String);
+    method public final void clearFragmentResult(String);
+    method public final void clearFragmentResultListener(String);
+    method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method @Deprecated public static void enableDebugLogging(boolean);
+    method @MainThread public boolean executePendingTransactions();
+    method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+    method public androidx.fragment.app.Fragment? findFragmentById(@IdRes int);
+    method public androidx.fragment.app.Fragment? findFragmentByTag(String?);
+    method public androidx.fragment.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+    method public int getBackStackEntryCount();
+    method public androidx.fragment.app.Fragment? getFragment(android.os.Bundle, String);
+    method public androidx.fragment.app.FragmentFactory getFragmentFactory();
+    method public java.util.List<androidx.fragment.app.Fragment!> getFragments();
+    method public androidx.fragment.app.Fragment? getPrimaryNavigationFragment();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy? getStrictModePolicy();
+    method public boolean isDestroyed();
+    method public boolean isStateSaved();
+    method public void popBackStack();
+    method public void popBackStack(String?, int);
+    method public void popBackStack(int, int);
+    method @MainThread public boolean popBackStackImmediate();
+    method @MainThread public boolean popBackStackImmediate(String?, int);
+    method public boolean popBackStackImmediate(int, int);
+    method public void putFragment(android.os.Bundle, String, androidx.fragment.app.Fragment);
+    method public void registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks, boolean);
+    method public void removeFragmentOnAttachListener(androidx.fragment.app.FragmentOnAttachListener);
+    method public void removeOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+    method public void restoreBackStack(String);
+    method public void saveBackStack(String);
+    method public androidx.fragment.app.Fragment.SavedState? saveFragmentInstanceState(androidx.fragment.app.Fragment);
+    method public void setFragmentFactory(androidx.fragment.app.FragmentFactory);
+    method public final void setFragmentResult(String, android.os.Bundle);
+    method public final void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+    method public void setStrictModePolicy(androidx.fragment.app.strictmode.FragmentStrictMode.Policy?);
+    method public void unregisterFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks);
+    field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+  }
+
+  public static interface FragmentManager.BackStackEntry {
+    method @Deprecated public CharSequence? getBreadCrumbShortTitle();
+    method @Deprecated @StringRes public int getBreadCrumbShortTitleRes();
+    method @Deprecated public CharSequence? getBreadCrumbTitle();
+    method @Deprecated @StringRes public int getBreadCrumbTitleRes();
+    method public int getId();
+    method public String? getName();
+  }
+
+  public abstract static class FragmentManager.FragmentLifecycleCallbacks {
+    ctor public FragmentManager.FragmentLifecycleCallbacks();
+    method @Deprecated public void onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+    method public void onFragmentCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentDetached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentPaused(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentPreAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+    method public void onFragmentPreCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentResumed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentSaveInstanceState(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle);
+    method public void onFragmentStarted(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentStopped(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentViewCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.view.View, android.os.Bundle?);
+    method public void onFragmentViewDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+  }
+
+  public static interface FragmentManager.OnBackStackChangedListener {
+    method @MainThread public default void onBackStackChangeCommitted(androidx.fragment.app.Fragment, boolean);
+    method @MainThread public default void onBackStackChangeStarted(androidx.fragment.app.Fragment, boolean);
+    method @MainThread public void onBackStackChanged();
+  }
+
+  @Deprecated public class FragmentManagerNonConfig {
+  }
+
+  public interface FragmentOnAttachListener {
+    method @MainThread public void onAttachFragment(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+  }
+
+  @Deprecated public abstract class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+    ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager);
+    ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager, int);
+    method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+    method @Deprecated public long getItemId(int);
+    method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+    field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+    field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+  }
+
+  public interface FragmentResultListener {
+    method public void onFragmentResult(String, android.os.Bundle);
+  }
+
+  public interface FragmentResultOwner {
+    method public void clearFragmentResult(String);
+    method public void clearFragmentResultListener(String);
+    method public void setFragmentResult(String, android.os.Bundle);
+    method public void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+  }
+
+  @Deprecated public abstract class FragmentStatePagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+    ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager);
+    ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager, int);
+    method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+    method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+    field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+    field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+  }
+
+  @Deprecated public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+    ctor @Deprecated public FragmentTabHost(android.content.Context);
+    ctor @Deprecated public FragmentTabHost(android.content.Context, android.util.AttributeSet?);
+    method @Deprecated public void addTab(android.widget.TabHost.TabSpec, Class<?>, android.os.Bundle?);
+    method @Deprecated public void onTabChanged(String?);
+    method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager);
+    method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager, int);
+  }
+
+  public abstract class FragmentTransaction {
+    ctor @Deprecated public FragmentTransaction();
+    method public final androidx.fragment.app.FragmentTransaction add(Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.Fragment, String?);
+    method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+    method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment, String?);
+    method public androidx.fragment.app.FragmentTransaction addSharedElement(android.view.View, String);
+    method public androidx.fragment.app.FragmentTransaction addToBackStack(String?);
+    method public androidx.fragment.app.FragmentTransaction attach(androidx.fragment.app.Fragment);
+    method public abstract int commit();
+    method public abstract int commitAllowingStateLoss();
+    method @MainThread public abstract void commitNow();
+    method @MainThread public abstract void commitNowAllowingStateLoss();
+    method public androidx.fragment.app.FragmentTransaction detach(androidx.fragment.app.Fragment);
+    method public androidx.fragment.app.FragmentTransaction disallowAddToBackStack();
+    method public androidx.fragment.app.FragmentTransaction hide(androidx.fragment.app.Fragment);
+    method public boolean isAddToBackStackAllowed();
+    method public boolean isEmpty();
+    method public androidx.fragment.app.FragmentTransaction remove(androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+    method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment, String?);
+    method public androidx.fragment.app.FragmentTransaction runOnCommit(Runnable);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setAllowOptimization(boolean);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(@StringRes int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(CharSequence?);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(@StringRes int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(CharSequence?);
+    method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+    method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+    method public androidx.fragment.app.FragmentTransaction setMaxLifecycle(androidx.fragment.app.Fragment, androidx.lifecycle.Lifecycle.State);
+    method public androidx.fragment.app.FragmentTransaction setPrimaryNavigationFragment(androidx.fragment.app.Fragment?);
+    method public androidx.fragment.app.FragmentTransaction setReorderingAllowed(boolean);
+    method public androidx.fragment.app.FragmentTransaction setTransition(int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setTransitionStyle(@StyleRes int);
+    method public androidx.fragment.app.FragmentTransaction show(androidx.fragment.app.Fragment);
+    field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+    field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+    field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+    field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+    field public static final int TRANSIT_FRAGMENT_MATCH_ACTIVITY_CLOSE = 8197; // 0x2005
+    field public static final int TRANSIT_FRAGMENT_MATCH_ACTIVITY_OPEN = 4100; // 0x1004
+    field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+    field public static final int TRANSIT_NONE = 0; // 0x0
+    field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+  }
+
+  public class ListFragment extends androidx.fragment.app.Fragment {
+    ctor public ListFragment();
+    method public android.widget.ListAdapter? getListAdapter();
+    method public android.widget.ListView getListView();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+    method public final android.widget.ListAdapter requireListAdapter();
+    method public void setEmptyText(CharSequence?);
+    method public void setListAdapter(android.widget.ListAdapter?);
+    method public void setListShown(boolean);
+    method public void setListShownNoAnimation(boolean);
+    method public void setSelection(int);
+  }
+
+}
+
+package androidx.fragment.app.strictmode {
+
+  public final class FragmentReuseViolation extends androidx.fragment.app.strictmode.Violation {
+    method public String getPreviousFragmentId();
+    property public final String previousFragmentId;
+  }
+
+  public final class FragmentStrictMode {
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy getDefaultPolicy();
+    method @VisibleForTesting public void onPolicyViolation(androidx.fragment.app.strictmode.Violation violation);
+    method public void setDefaultPolicy(androidx.fragment.app.strictmode.FragmentStrictMode.Policy);
+    property public final androidx.fragment.app.strictmode.FragmentStrictMode.Policy defaultPolicy;
+    field public static final androidx.fragment.app.strictmode.FragmentStrictMode INSTANCE;
+  }
+
+  public static fun interface FragmentStrictMode.OnViolationListener {
+    method public void onViolation(androidx.fragment.app.strictmode.Violation violation);
+  }
+
+  public static final class FragmentStrictMode.Policy {
+    field public static final androidx.fragment.app.strictmode.FragmentStrictMode.Policy LAX;
+  }
+
+  public static final class FragmentStrictMode.Policy.Builder {
+    ctor public FragmentStrictMode.Policy.Builder();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(Class<? extends androidx.fragment.app.Fragment> fragmentClass, Class<? extends androidx.fragment.app.strictmode.Violation> violationClass);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(String fragmentClass, Class<? extends androidx.fragment.app.strictmode.Violation> violationClass);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy build();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentReuse();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentTagUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectRetainInstanceUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectSetUserVisibleHint();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectTargetFragmentUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectWrongFragmentContainer();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectWrongNestedHierarchy();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyDeath();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyListener(androidx.fragment.app.strictmode.FragmentStrictMode.OnViolationListener listener);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyLog();
+  }
+
+  public final class FragmentTagUsageViolation extends androidx.fragment.app.strictmode.Violation {
+    method public android.view.ViewGroup? getParentContainer();
+    property public final android.view.ViewGroup? parentContainer;
+  }
+
+  public final class GetRetainInstanceUsageViolation extends androidx.fragment.app.strictmode.RetainInstanceUsageViolation {
+  }
+
+  public final class GetTargetFragmentRequestCodeUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+  }
+
+  public final class GetTargetFragmentUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+  }
+
+  public abstract class RetainInstanceUsageViolation extends androidx.fragment.app.strictmode.Violation {
+  }
+
+  public final class SetRetainInstanceUsageViolation extends androidx.fragment.app.strictmode.RetainInstanceUsageViolation {
+  }
+
+  public final class SetTargetFragmentUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+    method public int getRequestCode();
+    method public androidx.fragment.app.Fragment getTargetFragment();
+    property public final int requestCode;
+    property public final androidx.fragment.app.Fragment targetFragment;
+  }
+
+  public final class SetUserVisibleHintViolation extends androidx.fragment.app.strictmode.Violation {
+    method public boolean isVisibleToUser();
+    property public final boolean isVisibleToUser;
+  }
+
+  public abstract class TargetFragmentUsageViolation extends androidx.fragment.app.strictmode.Violation {
+  }
+
+  public abstract class Violation extends java.lang.RuntimeException {
+    method public final androidx.fragment.app.Fragment getFragment();
+    property public final androidx.fragment.app.Fragment fragment;
+  }
+
+  public final class WrongFragmentContainerViolation extends androidx.fragment.app.strictmode.Violation {
+    method public android.view.ViewGroup getContainer();
+    property public final android.view.ViewGroup container;
+  }
+
+  public final class WrongNestedHierarchyViolation extends androidx.fragment.app.strictmode.Violation {
+    method public int getContainerId();
+    method public androidx.fragment.app.Fragment getExpectedParentFragment();
+    property public final int containerId;
+    property public final androidx.fragment.app.Fragment expectedParentFragment;
+  }
+
+}
+
diff --git a/fragment/fragment/api/res-1.6.0-beta02.txt b/fragment/fragment/api/res-1.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment/api/res-1.6.0-beta02.txt
diff --git a/fragment/fragment/api/restricted_1.6.0-beta02.txt b/fragment/fragment/api/restricted_1.6.0-beta02.txt
new file mode 100644
index 0000000..369fe63
--- /dev/null
+++ b/fragment/fragment/api/restricted_1.6.0-beta02.txt
@@ -0,0 +1,583 @@
+// Signature format: 4.0
+package androidx.fragment.app {
+
+  public class DialogFragment extends androidx.fragment.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+    ctor public DialogFragment();
+    ctor public DialogFragment(@LayoutRes int);
+    method public void dismiss();
+    method public void dismissAllowingStateLoss();
+    method @MainThread public void dismissNow();
+    method public android.app.Dialog? getDialog();
+    method public boolean getShowsDialog();
+    method @StyleRes public int getTheme();
+    method public boolean isCancelable();
+    method public void onCancel(android.content.DialogInterface);
+    method @MainThread public android.app.Dialog onCreateDialog(android.os.Bundle?);
+    method @CallSuper public void onDismiss(android.content.DialogInterface);
+    method public final androidx.activity.ComponentDialog requireComponentDialog();
+    method public final android.app.Dialog requireDialog();
+    method public void setCancelable(boolean);
+    method public void setShowsDialog(boolean);
+    method public void setStyle(int, @StyleRes int);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setupDialog(android.app.Dialog, int);
+    method public void show(androidx.fragment.app.FragmentManager, String?);
+    method public int show(androidx.fragment.app.FragmentTransaction, String?);
+    method public void showNow(androidx.fragment.app.FragmentManager, String?);
+    field public static final int STYLE_NORMAL = 0; // 0x0
+    field public static final int STYLE_NO_FRAME = 2; // 0x2
+    field public static final int STYLE_NO_INPUT = 3; // 0x3
+    field public static final int STYLE_NO_TITLE = 1; // 0x1
+  }
+
+  public class Fragment implements androidx.activity.result.ActivityResultCaller android.content.ComponentCallbacks androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner android.view.View.OnCreateContextMenuListener androidx.lifecycle.ViewModelStoreOwner {
+    ctor public Fragment();
+    ctor @ContentView public Fragment(@LayoutRes int);
+    method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public final boolean equals(Object?);
+    method public final androidx.fragment.app.FragmentActivity? getActivity();
+    method public boolean getAllowEnterTransitionOverlap();
+    method public boolean getAllowReturnTransitionOverlap();
+    method public final android.os.Bundle? getArguments();
+    method public final androidx.fragment.app.FragmentManager getChildFragmentManager();
+    method public android.content.Context? getContext();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public Object? getEnterTransition();
+    method public Object? getExitTransition();
+    method @Deprecated public final androidx.fragment.app.FragmentManager? getFragmentManager();
+    method public final Object? getHost();
+    method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
+    method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.view.LayoutInflater getLayoutInflater(android.os.Bundle?);
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @Deprecated public androidx.loader.app.LoaderManager getLoaderManager();
+    method public final androidx.fragment.app.Fragment? getParentFragment();
+    method public final androidx.fragment.app.FragmentManager getParentFragmentManager();
+    method public Object? getReenterTransition();
+    method public final android.content.res.Resources getResources();
+    method @Deprecated public final boolean getRetainInstance();
+    method public Object? getReturnTransition();
+    method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public Object? getSharedElementEnterTransition();
+    method public Object? getSharedElementReturnTransition();
+    method public final String getString(@StringRes int);
+    method public final String getString(@StringRes int, java.lang.Object!...);
+    method public final String? getTag();
+    method @Deprecated public final androidx.fragment.app.Fragment? getTargetFragment();
+    method @Deprecated public final int getTargetRequestCode();
+    method public final CharSequence getText(@StringRes int);
+    method @Deprecated public boolean getUserVisibleHint();
+    method public android.view.View? getView();
+    method @MainThread public androidx.lifecycle.LifecycleOwner getViewLifecycleOwner();
+    method public androidx.lifecycle.LiveData<androidx.lifecycle.LifecycleOwner!> getViewLifecycleOwnerLiveData();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final boolean hasOptionsMenu();
+    method public final int hashCode();
+    method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String);
+    method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+    method public final boolean isAdded();
+    method public final boolean isDetached();
+    method public final boolean isHidden();
+    method public final boolean isInLayout();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final boolean isMenuVisible();
+    method public final boolean isRemoving();
+    method public final boolean isResumed();
+    method public final boolean isStateSaved();
+    method public final boolean isVisible();
+    method @Deprecated @CallSuper @MainThread public void onActivityCreated(android.os.Bundle?);
+    method @Deprecated public void onActivityResult(int, int, android.content.Intent?);
+    method @CallSuper @MainThread public void onAttach(android.content.Context);
+    method @Deprecated @CallSuper @MainThread public void onAttach(android.app.Activity);
+    method @Deprecated @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+    method @CallSuper public void onConfigurationChanged(android.content.res.Configuration);
+    method @MainThread public boolean onContextItemSelected(android.view.MenuItem);
+    method @CallSuper @MainThread public void onCreate(android.os.Bundle?);
+    method @MainThread public android.view.animation.Animation? onCreateAnimation(int, boolean, int);
+    method @MainThread public android.animation.Animator? onCreateAnimator(int, boolean, int);
+    method @MainThread public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo?);
+    method @Deprecated @MainThread public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method @MainThread public android.view.View? onCreateView(android.view.LayoutInflater, android.view.ViewGroup?, android.os.Bundle?);
+    method @CallSuper @MainThread public void onDestroy();
+    method @Deprecated @MainThread public void onDestroyOptionsMenu();
+    method @CallSuper @MainThread public void onDestroyView();
+    method @CallSuper @MainThread public void onDetach();
+    method public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle?);
+    method @MainThread public void onHiddenChanged(boolean);
+    method @CallSuper @UiThread public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle?);
+    method @Deprecated @CallSuper @UiThread public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle?);
+    method @CallSuper @MainThread public void onLowMemory();
+    method public void onMultiWindowModeChanged(boolean);
+    method @Deprecated @MainThread public boolean onOptionsItemSelected(android.view.MenuItem);
+    method @Deprecated @MainThread public void onOptionsMenuClosed(android.view.Menu);
+    method @CallSuper @MainThread public void onPause();
+    method public void onPictureInPictureModeChanged(boolean);
+    method @Deprecated @MainThread public void onPrepareOptionsMenu(android.view.Menu);
+    method @MainThread public void onPrimaryNavigationFragmentChanged(boolean);
+    method @Deprecated public void onRequestPermissionsResult(int, String![], int[]);
+    method @CallSuper @MainThread public void onResume();
+    method @MainThread public void onSaveInstanceState(android.os.Bundle);
+    method @CallSuper @MainThread public void onStart();
+    method @CallSuper @MainThread public void onStop();
+    method @MainThread public void onViewCreated(android.view.View, android.os.Bundle?);
+    method @CallSuper @MainThread public void onViewStateRestored(android.os.Bundle?);
+    method public void postponeEnterTransition();
+    method public final void postponeEnterTransition(long, java.util.concurrent.TimeUnit);
+    method @MainThread public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+    method @MainThread public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+    method public void registerForContextMenu(android.view.View);
+    method @Deprecated public final void requestPermissions(String![], int);
+    method public final androidx.fragment.app.FragmentActivity requireActivity();
+    method public final android.os.Bundle requireArguments();
+    method public final android.content.Context requireContext();
+    method @Deprecated public final androidx.fragment.app.FragmentManager requireFragmentManager();
+    method public final Object requireHost();
+    method public final androidx.fragment.app.Fragment requireParentFragment();
+    method public final android.view.View requireView();
+    method public void setAllowEnterTransitionOverlap(boolean);
+    method public void setAllowReturnTransitionOverlap(boolean);
+    method public void setArguments(android.os.Bundle?);
+    method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setEnterTransition(Object?);
+    method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setExitTransition(Object?);
+    method @Deprecated public void setHasOptionsMenu(boolean);
+    method public void setInitialSavedState(androidx.fragment.app.Fragment.SavedState?);
+    method public void setMenuVisibility(boolean);
+    method public void setReenterTransition(Object?);
+    method @Deprecated public void setRetainInstance(boolean);
+    method public void setReturnTransition(Object?);
+    method public void setSharedElementEnterTransition(Object?);
+    method public void setSharedElementReturnTransition(Object?);
+    method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
+    method @Deprecated public void setUserVisibleHint(boolean);
+    method public boolean shouldShowRequestPermissionRationale(String);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle?);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startPostponedEnterTransition();
+    method public void unregisterForContextMenu(android.view.View);
+  }
+
+  public static class Fragment.InstantiationException extends java.lang.RuntimeException {
+    ctor public Fragment.InstantiationException(String, Exception?);
+  }
+
+  public static class Fragment.SavedState implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<androidx.fragment.app.Fragment.SavedState!> CREATOR;
+  }
+
+  public class FragmentActivity extends androidx.activity.ComponentActivity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback androidx.core.app.ActivityCompat.RequestPermissionsRequestCodeValidator {
+    ctor public FragmentActivity();
+    ctor @ContentView public FragmentActivity(@LayoutRes int);
+    method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+    method @Deprecated public androidx.loader.app.LoaderManager getSupportLoaderManager();
+    method @Deprecated @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+    method protected void onResumeFragments();
+    method public void onStateNotSaved();
+    method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void supportFinishAfterTransition();
+    method @Deprecated public void supportInvalidateOptionsMenu();
+    method public void supportPostponeEnterTransition();
+    method public void supportStartPostponedEnterTransition();
+    method @Deprecated public final void validateRequestPermissionsRequestCode(int);
+  }
+
+  public abstract class FragmentContainer {
+    ctor public FragmentContainer();
+    method @Deprecated public androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+    method public abstract android.view.View? onFindViewById(@IdRes int);
+    method public abstract boolean onHasView();
+  }
+
+  public final class FragmentContainerView extends android.widget.FrameLayout {
+    ctor public FragmentContainerView(android.content.Context context);
+    ctor public FragmentContainerView(android.content.Context context, android.util.AttributeSet? attrs, optional int defStyleAttr);
+    ctor public FragmentContainerView(android.content.Context context, android.util.AttributeSet? attrs);
+    method public <F extends androidx.fragment.app.Fragment> F getFragment();
+  }
+
+  public class FragmentController {
+    method public void attachHost(androidx.fragment.app.Fragment?);
+    method public static androidx.fragment.app.FragmentController createController(androidx.fragment.app.FragmentHostCallback<?>);
+    method public void dispatchActivityCreated();
+    method @Deprecated public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public boolean dispatchContextItemSelected(android.view.MenuItem);
+    method public void dispatchCreate();
+    method @Deprecated public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public void dispatchDestroy();
+    method public void dispatchDestroyView();
+    method @Deprecated public void dispatchLowMemory();
+    method @Deprecated public void dispatchMultiWindowModeChanged(boolean);
+    method @Deprecated public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+    method @Deprecated public void dispatchOptionsMenuClosed(android.view.Menu);
+    method public void dispatchPause();
+    method @Deprecated public void dispatchPictureInPictureModeChanged(boolean);
+    method @Deprecated public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+    method @Deprecated public void dispatchReallyStop();
+    method public void dispatchResume();
+    method public void dispatchStart();
+    method public void dispatchStop();
+    method @Deprecated public void doLoaderDestroy();
+    method @Deprecated public void doLoaderRetain();
+    method @Deprecated public void doLoaderStart();
+    method @Deprecated public void doLoaderStop(boolean);
+    method @Deprecated public void dumpLoaders(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public boolean execPendingActions();
+    method public androidx.fragment.app.Fragment? findFragmentByWho(String);
+    method public java.util.List<androidx.fragment.app.Fragment!> getActiveFragments(java.util.List<androidx.fragment.app.Fragment!>!);
+    method public int getActiveFragmentsCount();
+    method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+    method @Deprecated public androidx.loader.app.LoaderManager! getSupportLoaderManager();
+    method public void noteStateNotSaved();
+    method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
+    method @Deprecated public void reportLoaderStart();
+    method @Deprecated public void restoreAllState(android.os.Parcelable?, java.util.List<androidx.fragment.app.Fragment!>?);
+    method @Deprecated public void restoreAllState(android.os.Parcelable?, androidx.fragment.app.FragmentManagerNonConfig?);
+    method @Deprecated public void restoreLoaderNonConfig(androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>!);
+    method @Deprecated public void restoreSaveState(android.os.Parcelable?);
+    method @Deprecated public androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>? retainLoaderNonConfig();
+    method @Deprecated public androidx.fragment.app.FragmentManagerNonConfig? retainNestedNonConfig();
+    method @Deprecated public java.util.List<androidx.fragment.app.Fragment!>? retainNonConfig();
+    method @Deprecated public android.os.Parcelable? saveAllState();
+  }
+
+  public class FragmentFactory {
+    ctor public FragmentFactory();
+    method public androidx.fragment.app.Fragment instantiate(ClassLoader, String);
+    method public static Class<? extends androidx.fragment.app.Fragment> loadFragmentClass(ClassLoader, String);
+  }
+
+  public abstract class FragmentHostCallback<E> extends androidx.fragment.app.FragmentContainer {
+    ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+    method public void onDump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method public android.view.View? onFindViewById(int);
+    method public abstract E? onGetHost();
+    method public android.view.LayoutInflater onGetLayoutInflater();
+    method public int onGetWindowAnimations();
+    method public boolean onHasView();
+    method public boolean onHasWindowAnimations();
+    method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
+    method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
+    method public boolean onShouldShowRequestPermissionRationale(String);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void onSupportInvalidateOptionsMenu();
+  }
+
+  public abstract class FragmentManager implements androidx.fragment.app.FragmentResultOwner {
+    ctor public FragmentManager();
+    method public void addFragmentOnAttachListener(androidx.fragment.app.FragmentOnAttachListener);
+    method public void addOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+    method public androidx.fragment.app.FragmentTransaction beginTransaction();
+    method public void clearBackStack(String);
+    method public final void clearFragmentResult(String);
+    method public final void clearFragmentResultListener(String);
+    method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+    method @Deprecated public static void enableDebugLogging(boolean);
+    method @MainThread public boolean executePendingTransactions();
+    method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+    method public androidx.fragment.app.Fragment? findFragmentById(@IdRes int);
+    method public androidx.fragment.app.Fragment? findFragmentByTag(String?);
+    method public androidx.fragment.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+    method public int getBackStackEntryCount();
+    method public androidx.fragment.app.Fragment? getFragment(android.os.Bundle, String);
+    method public androidx.fragment.app.FragmentFactory getFragmentFactory();
+    method public java.util.List<androidx.fragment.app.Fragment!> getFragments();
+    method public androidx.fragment.app.Fragment? getPrimaryNavigationFragment();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy? getStrictModePolicy();
+    method public boolean isDestroyed();
+    method public boolean isStateSaved();
+    method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.fragment.app.FragmentTransaction openTransaction();
+    method public void popBackStack();
+    method public void popBackStack(String?, int);
+    method public void popBackStack(int, int);
+    method @MainThread public boolean popBackStackImmediate();
+    method @MainThread public boolean popBackStackImmediate(String?, int);
+    method public boolean popBackStackImmediate(int, int);
+    method public void putFragment(android.os.Bundle, String, androidx.fragment.app.Fragment);
+    method public void registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks, boolean);
+    method public void removeFragmentOnAttachListener(androidx.fragment.app.FragmentOnAttachListener);
+    method public void removeOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+    method public void restoreBackStack(String);
+    method public void saveBackStack(String);
+    method public androidx.fragment.app.Fragment.SavedState? saveFragmentInstanceState(androidx.fragment.app.Fragment);
+    method public void setFragmentFactory(androidx.fragment.app.FragmentFactory);
+    method public final void setFragmentResult(String, android.os.Bundle);
+    method public final void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+    method public void setStrictModePolicy(androidx.fragment.app.strictmode.FragmentStrictMode.Policy?);
+    method public void unregisterFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks);
+    field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+  }
+
+  public static interface FragmentManager.BackStackEntry {
+    method @Deprecated public CharSequence? getBreadCrumbShortTitle();
+    method @Deprecated @StringRes public int getBreadCrumbShortTitleRes();
+    method @Deprecated public CharSequence? getBreadCrumbTitle();
+    method @Deprecated @StringRes public int getBreadCrumbTitleRes();
+    method public int getId();
+    method public String? getName();
+  }
+
+  public abstract static class FragmentManager.FragmentLifecycleCallbacks {
+    ctor public FragmentManager.FragmentLifecycleCallbacks();
+    method @Deprecated public void onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+    method public void onFragmentCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentDetached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentPaused(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentPreAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+    method public void onFragmentPreCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+    method public void onFragmentResumed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentSaveInstanceState(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle);
+    method public void onFragmentStarted(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentStopped(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+    method public void onFragmentViewCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.view.View, android.os.Bundle?);
+    method public void onFragmentViewDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+  }
+
+  public static interface FragmentManager.OnBackStackChangedListener {
+    method @MainThread public default void onBackStackChangeCommitted(androidx.fragment.app.Fragment, boolean);
+    method @MainThread public default void onBackStackChangeStarted(androidx.fragment.app.Fragment, boolean);
+    method @MainThread public void onBackStackChanged();
+  }
+
+  @Deprecated public class FragmentManagerNonConfig {
+  }
+
+  public interface FragmentOnAttachListener {
+    method @MainThread public void onAttachFragment(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+  }
+
+  @Deprecated public abstract class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+    ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager);
+    ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager, int);
+    method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+    method @Deprecated public long getItemId(int);
+    method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+    field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+    field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+  }
+
+  public interface FragmentResultListener {
+    method public void onFragmentResult(String, android.os.Bundle);
+  }
+
+  public interface FragmentResultOwner {
+    method public void clearFragmentResult(String);
+    method public void clearFragmentResultListener(String);
+    method public void setFragmentResult(String, android.os.Bundle);
+    method public void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+  }
+
+  @Deprecated public abstract class FragmentStatePagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+    ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager);
+    ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager, int);
+    method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+    method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+    field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+    field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+  }
+
+  @Deprecated public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+    ctor @Deprecated public FragmentTabHost(android.content.Context);
+    ctor @Deprecated public FragmentTabHost(android.content.Context, android.util.AttributeSet?);
+    method @Deprecated public void addTab(android.widget.TabHost.TabSpec, Class<?>, android.os.Bundle?);
+    method @Deprecated public void onTabChanged(String?);
+    method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager);
+    method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager, int);
+  }
+
+  public abstract class FragmentTransaction {
+    ctor @Deprecated public FragmentTransaction();
+    method public final androidx.fragment.app.FragmentTransaction add(Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.Fragment, String?);
+    method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+    method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment, String?);
+    method public androidx.fragment.app.FragmentTransaction addSharedElement(android.view.View, String);
+    method public androidx.fragment.app.FragmentTransaction addToBackStack(String?);
+    method public androidx.fragment.app.FragmentTransaction attach(androidx.fragment.app.Fragment);
+    method public abstract int commit();
+    method public abstract int commitAllowingStateLoss();
+    method @MainThread public abstract void commitNow();
+    method @MainThread public abstract void commitNowAllowingStateLoss();
+    method public androidx.fragment.app.FragmentTransaction detach(androidx.fragment.app.Fragment);
+    method public androidx.fragment.app.FragmentTransaction disallowAddToBackStack();
+    method public androidx.fragment.app.FragmentTransaction hide(androidx.fragment.app.Fragment);
+    method public boolean isAddToBackStackAllowed();
+    method public boolean isEmpty();
+    method public androidx.fragment.app.FragmentTransaction remove(androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+    method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment);
+    method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+    method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment, String?);
+    method public androidx.fragment.app.FragmentTransaction runOnCommit(Runnable);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setAllowOptimization(boolean);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(@StringRes int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(CharSequence?);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(@StringRes int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(CharSequence?);
+    method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+    method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+    method public androidx.fragment.app.FragmentTransaction setMaxLifecycle(androidx.fragment.app.Fragment, androidx.lifecycle.Lifecycle.State);
+    method public androidx.fragment.app.FragmentTransaction setPrimaryNavigationFragment(androidx.fragment.app.Fragment?);
+    method public androidx.fragment.app.FragmentTransaction setReorderingAllowed(boolean);
+    method public androidx.fragment.app.FragmentTransaction setTransition(int);
+    method @Deprecated public androidx.fragment.app.FragmentTransaction setTransitionStyle(@StyleRes int);
+    method public androidx.fragment.app.FragmentTransaction show(androidx.fragment.app.Fragment);
+    field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+    field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+    field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+    field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+    field public static final int TRANSIT_FRAGMENT_MATCH_ACTIVITY_CLOSE = 8197; // 0x2005
+    field public static final int TRANSIT_FRAGMENT_MATCH_ACTIVITY_OPEN = 4100; // 0x1004
+    field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+    field public static final int TRANSIT_NONE = 0; // 0x0
+    field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class FragmentTransitionImpl {
+    ctor public FragmentTransitionImpl();
+    method public abstract void addTarget(Object, android.view.View);
+    method public abstract void addTargets(Object, java.util.ArrayList<android.view.View!>);
+    method public abstract void beginDelayedTransition(android.view.ViewGroup, Object?);
+    method protected static void bfsAddViewChildren(java.util.List<android.view.View!>!, android.view.View!);
+    method public abstract boolean canHandle(Object);
+    method public abstract Object! cloneTransition(Object?);
+    method protected void getBoundsOnScreen(android.view.View!, android.graphics.Rect!);
+    method protected static boolean isNullOrEmpty(java.util.List!);
+    method public abstract Object! mergeTransitionsInSequence(Object?, Object?, Object?);
+    method public abstract Object! mergeTransitionsTogether(Object?, Object?, Object?);
+    method public abstract void removeTarget(Object, android.view.View);
+    method public abstract void replaceTargets(Object, java.util.ArrayList<android.view.View!>!, java.util.ArrayList<android.view.View!>!);
+    method public abstract void scheduleHideFragmentView(Object, android.view.View, java.util.ArrayList<android.view.View!>);
+    method public abstract void scheduleRemoveTargets(Object, Object?, java.util.ArrayList<android.view.View!>?, Object?, java.util.ArrayList<android.view.View!>?, Object?, java.util.ArrayList<android.view.View!>?);
+    method public abstract void setEpicenter(Object, android.view.View?);
+    method public abstract void setEpicenter(Object, android.graphics.Rect);
+    method public void setListenerForTransitionEnd(androidx.fragment.app.Fragment, Object, androidx.core.os.CancellationSignal, Runnable);
+    method public abstract void setSharedElementTargets(Object, android.view.View, java.util.ArrayList<android.view.View!>);
+    method public abstract void swapSharedElementTargets(Object?, java.util.ArrayList<android.view.View!>?, java.util.ArrayList<android.view.View!>?);
+    method public abstract Object! wrapTransitionInSet(Object?);
+  }
+
+  public class ListFragment extends androidx.fragment.app.Fragment {
+    ctor public ListFragment();
+    method public android.widget.ListAdapter? getListAdapter();
+    method public android.widget.ListView getListView();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+    method public final android.widget.ListAdapter requireListAdapter();
+    method public void setEmptyText(CharSequence?);
+    method public void setListAdapter(android.widget.ListAdapter?);
+    method public void setListShown(boolean);
+    method public void setListShownNoAnimation(boolean);
+    method public void setSelection(int);
+  }
+
+}
+
+package androidx.fragment.app.strictmode {
+
+  public final class FragmentReuseViolation extends androidx.fragment.app.strictmode.Violation {
+    method public String getPreviousFragmentId();
+    property public final String previousFragmentId;
+  }
+
+  public final class FragmentStrictMode {
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy getDefaultPolicy();
+    method @VisibleForTesting public void onPolicyViolation(androidx.fragment.app.strictmode.Violation violation);
+    method public void setDefaultPolicy(androidx.fragment.app.strictmode.FragmentStrictMode.Policy);
+    property public final androidx.fragment.app.strictmode.FragmentStrictMode.Policy defaultPolicy;
+    field public static final androidx.fragment.app.strictmode.FragmentStrictMode INSTANCE;
+  }
+
+  public static fun interface FragmentStrictMode.OnViolationListener {
+    method public void onViolation(androidx.fragment.app.strictmode.Violation violation);
+  }
+
+  public static final class FragmentStrictMode.Policy {
+    field public static final androidx.fragment.app.strictmode.FragmentStrictMode.Policy LAX;
+  }
+
+  public static final class FragmentStrictMode.Policy.Builder {
+    ctor public FragmentStrictMode.Policy.Builder();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(Class<? extends androidx.fragment.app.Fragment> fragmentClass, Class<? extends androidx.fragment.app.strictmode.Violation> violationClass);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(String fragmentClass, Class<? extends androidx.fragment.app.strictmode.Violation> violationClass);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy build();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentReuse();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentTagUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectRetainInstanceUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectSetUserVisibleHint();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectTargetFragmentUsage();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectWrongFragmentContainer();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectWrongNestedHierarchy();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyDeath();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyListener(androidx.fragment.app.strictmode.FragmentStrictMode.OnViolationListener listener);
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder penaltyLog();
+  }
+
+  public final class FragmentTagUsageViolation extends androidx.fragment.app.strictmode.Violation {
+    method public android.view.ViewGroup? getParentContainer();
+    property public final android.view.ViewGroup? parentContainer;
+  }
+
+  public final class GetRetainInstanceUsageViolation extends androidx.fragment.app.strictmode.RetainInstanceUsageViolation {
+  }
+
+  public final class GetTargetFragmentRequestCodeUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+  }
+
+  public final class GetTargetFragmentUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+  }
+
+  public abstract class RetainInstanceUsageViolation extends androidx.fragment.app.strictmode.Violation {
+  }
+
+  public final class SetRetainInstanceUsageViolation extends androidx.fragment.app.strictmode.RetainInstanceUsageViolation {
+  }
+
+  public final class SetTargetFragmentUsageViolation extends androidx.fragment.app.strictmode.TargetFragmentUsageViolation {
+    method public int getRequestCode();
+    method public androidx.fragment.app.Fragment getTargetFragment();
+    property public final int requestCode;
+    property public final androidx.fragment.app.Fragment targetFragment;
+  }
+
+  public final class SetUserVisibleHintViolation extends androidx.fragment.app.strictmode.Violation {
+    method public boolean isVisibleToUser();
+    property public final boolean isVisibleToUser;
+  }
+
+  public abstract class TargetFragmentUsageViolation extends androidx.fragment.app.strictmode.Violation {
+  }
+
+  public abstract class Violation extends java.lang.RuntimeException {
+    method public final androidx.fragment.app.Fragment getFragment();
+    property public final androidx.fragment.app.Fragment fragment;
+  }
+
+  public final class WrongFragmentContainerViolation extends androidx.fragment.app.strictmode.Violation {
+    method public android.view.ViewGroup getContainer();
+    property public final android.view.ViewGroup container;
+  }
+
+  public final class WrongNestedHierarchyViolation extends androidx.fragment.app.strictmode.Violation {
+    method public int getContainerId();
+    method public androidx.fragment.app.Fragment getExpectedParentFragment();
+    property public final int containerId;
+    property public final androidx.fragment.app.Fragment expectedParentFragment;
+  }
+
+}
+
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt
index 02fa8c0..f331268 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt
@@ -404,4 +404,45 @@
             assertThat(committedCount).isEqualTo(0)
         }
     }
+
+    @Test
+    fun testOnBackChangeNoAddToBackstackWithAddToBackStack() {
+        with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+            val fragmentManager = withActivity { supportFragmentManager }
+
+            val fragment = StrictFragment()
+            val fragment2 = StrictFragment()
+            var startedCount = 0
+            var committedCount = 0
+            val listener = object : OnBackStackChangedListener {
+                override fun onBackStackChanged() { /* nothing */ }
+
+                override fun onBackStackChangeStarted(fragment: Fragment, pop: Boolean) {
+                    startedCount++
+                }
+
+                override fun onBackStackChangeCommitted(fragment: Fragment, pop: Boolean) {
+                    committedCount++
+                }
+            }
+            fragmentManager.addOnBackStackChangedListener(listener)
+
+            withActivity {
+                fragmentManager.beginTransaction()
+                    .setReorderingAllowed(true)
+                    .add(R.id.content, fragment)
+                    .commit()
+
+                fragmentManager.beginTransaction()
+                    .setReorderingAllowed(true)
+                    .add(R.id.content, fragment2)
+                    .addToBackStack(null)
+                    .commit()
+                executePendingTransactions()
+            }
+
+            assertThat(startedCount).isEqualTo(1)
+            assertThat(committedCount).isEqualTo(1)
+        }
+    }
 }
\ No newline at end of file
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index dae7831..01cd33a 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -2139,7 +2139,7 @@
         Set<Fragment> fragments = new HashSet<>();
         for (int i = 0; i < record.mOps.size(); i++) {
             Fragment f = record.mOps.get(i).mFragment;
-            if (f != null) {
+            if (f != null && record.mAddToBackStack) {
                 fragments.add(f);
             }
         }
diff --git a/glance/glance-appwidget-preview/api/1.0.0-beta01.txt b/glance/glance-appwidget-preview/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/glance/glance-appwidget-preview/api/1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/glance/glance-appwidget-preview/api/public_plus_experimental_1.0.0-beta01.txt b/glance/glance-appwidget-preview/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/glance/glance-appwidget-preview/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/glance/glance-appwidget-preview/api/res-1.0.0-beta01.txt b/glance/glance-appwidget-preview/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/glance/glance-appwidget-preview/api/res-1.0.0-beta01.txt
diff --git a/glance/glance-appwidget-preview/api/restricted_1.0.0-beta01.txt b/glance/glance-appwidget-preview/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/glance/glance-appwidget-preview/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/glance/glance-appwidget-preview/build.gradle b/glance/glance-appwidget-preview/build.gradle
index bb9faa2..07567f5 100644
--- a/glance/glance-appwidget-preview/build.gradle
+++ b/glance/glance-appwidget-preview/build.gradle
@@ -35,7 +35,7 @@
 
     implementation("androidx.core:core:1.1.0")
 
-    api(project(":compose:runtime:runtime"))
+    api("androidx.compose.runtime:runtime:1.2.1")
     api(project(":glance:glance"))
     api(project(":glance:glance-appwidget"))
 
@@ -54,6 +54,7 @@
 androidx {
     name = "Android Glance AppWidget Preview"
     type = LibraryType.PUBLISHED_LIBRARY
+    mavenVersion = LibraryVersions.GLANCE_PREVIEW
     inceptionYear = "2022"
     description = "Glance tooling library. This library provides the API required for the " +
             "GlanceAppWidget components and its Glance @Composable to be previewable in the IDE."
diff --git a/glance/glance-appwidget/api/1.0.0-beta01.txt b/glance/glance-appwidget/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..72717d0
--- /dev/null
+++ b/glance/glance-appwidget/api/1.0.0-beta01.txt
@@ -0,0 +1,264 @@
+// Signature format: 4.0
+package androidx.glance.appwidget {
+
+  public final class AndroidRemoteViewsKt {
+    method @androidx.compose.runtime.Composable public static void AndroidRemoteViews(android.widget.RemoteViews remoteViews, optional androidx.glance.GlanceModifier modifier);
+    method @androidx.compose.runtime.Composable public static void AndroidRemoteViews(android.widget.RemoteViews remoteViews, @IdRes int containerViewId, optional androidx.glance.GlanceModifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class AppWidgetBackgroundKt {
+    method public static androidx.glance.GlanceModifier appWidgetBackground(androidx.glance.GlanceModifier);
+  }
+
+  public final class AppWidgetComposerKt {
+    method public static suspend Object? compose(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId id, optional android.os.Bundle? options, optional androidx.compose.ui.unit.DpSize? size, optional Object? state, optional kotlin.coroutines.Continuation<? super android.widget.RemoteViews>);
+  }
+
+  public final class BackgroundKt {
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, long day, long night);
+  }
+
+  public abstract sealed class CheckBoxColors {
+  }
+
+  public final class CheckBoxKt {
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors, optional int maxLines);
+  }
+
+  public final class CheckboxDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors(androidx.glance.unit.ColorProvider checkedColor, androidx.glance.unit.ColorProvider uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors(long checkedColor, long uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors();
+    field public static final androidx.glance.appwidget.CheckboxDefaults INSTANCE;
+  }
+
+  public final class CircularProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color);
+  }
+
+  public final class CompositionLocalsKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> getLocalAppWidgetOptions();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> LocalAppWidgetOptions;
+  }
+
+  public final class CornerRadiusKt {
+    method public static androidx.glance.GlanceModifier cornerRadius(androidx.glance.GlanceModifier, float radius);
+    method public static androidx.glance.GlanceModifier cornerRadius(androidx.glance.GlanceModifier, @DimenRes int radius);
+  }
+
+  public abstract class GlanceAppWidget {
+    ctor public GlanceAppWidget(optional @LayoutRes int errorUiLayout);
+    method public androidx.glance.appwidget.SizeMode getSizeMode();
+    method public androidx.glance.state.GlanceStateDefinition<?>? getStateDefinition();
+    method public suspend Object? onDelete(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public abstract suspend Object? provideGlance(android.content.Context context, androidx.glance.GlanceId id, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final suspend Object? update(android.content.Context context, androidx.glance.GlanceId id, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public androidx.glance.appwidget.SizeMode sizeMode;
+    property public androidx.glance.state.GlanceStateDefinition<?>? stateDefinition;
+  }
+
+  public final class GlanceAppWidgetKt {
+    method public static suspend Object? provideContent(androidx.glance.appwidget.GlanceAppWidget, kotlin.jvm.functions.Function0<kotlin.Unit> content, kotlin.coroutines.Continuation<?>);
+    method public static suspend Object? updateAll(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static suspend inline <reified State> void updateIf(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.jvm.functions.Function1<? super State,? extends java.lang.Boolean> predicate);
+  }
+
+  public final class GlanceAppWidgetManager {
+    ctor public GlanceAppWidgetManager(android.content.Context context);
+    method public int getAppWidgetId(androidx.glance.GlanceId glanceId);
+    method public suspend Object? getAppWidgetSizes(androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.compose.ui.unit.DpSize>>);
+    method public androidx.glance.GlanceId getGlanceIdBy(int appWidgetId);
+    method public androidx.glance.GlanceId? getGlanceIdBy(android.content.Intent configurationIntent);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidget> Object? getGlanceIds(Class<T> provider, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.glance.GlanceId>>);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional Object? previewState, optional android.app.PendingIntent? successCallback, optional kotlin.coroutines.Continuation<? super java.lang.Boolean>);
+  }
+
+  public abstract class GlanceAppWidgetReceiver extends android.appwidget.AppWidgetProvider {
+    ctor public GlanceAppWidgetReceiver();
+    method public abstract androidx.glance.appwidget.GlanceAppWidget getGlanceAppWidget();
+    property public abstract androidx.glance.appwidget.GlanceAppWidget glanceAppWidget;
+    field public static final String ACTION_DEBUG_UPDATE = "androidx.glance.appwidget.action.DEBUG_UPDATE";
+    field public static final androidx.glance.appwidget.GlanceAppWidgetReceiver.Companion Companion;
+  }
+
+  public static final class GlanceAppWidgetReceiver.Companion {
+  }
+
+  public final class ImageProvidersKt {
+    method public static androidx.glance.ImageProvider ImageProvider(android.net.Uri uri);
+  }
+
+  public final class LinearProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color, optional androidx.glance.unit.ColorProvider backgroundColor);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color, optional androidx.glance.unit.ColorProvider backgroundColor);
+  }
+
+  public final class ProgressIndicatorDefaults {
+    method public androidx.glance.unit.ColorProvider getBackgroundColorProvider();
+    method public androidx.glance.unit.ColorProvider getIndicatorColorProvider();
+    property public final androidx.glance.unit.ColorProvider BackgroundColorProvider;
+    property public final androidx.glance.unit.ColorProvider IndicatorColorProvider;
+    field public static final androidx.glance.appwidget.ProgressIndicatorDefaults INSTANCE;
+  }
+
+  public final class RadioButtonColors {
+  }
+
+  public final class RadioButtonDefaults {
+    method public androidx.glance.appwidget.RadioButtonColors colors(androidx.glance.unit.ColorProvider checkedColor, androidx.glance.unit.ColorProvider uncheckedColor);
+    method public androidx.glance.appwidget.RadioButtonColors colors(long checkedColor, long uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.RadioButtonColors colors();
+    field public static final androidx.glance.appwidget.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean checked, androidx.glance.action.Action? onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.RadioButtonColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.RadioButtonColors colors, optional int maxLines);
+    method public static androidx.glance.GlanceModifier selectableGroup(androidx.glance.GlanceModifier);
+  }
+
+  public sealed interface SizeMode {
+  }
+
+  public static final class SizeMode.Exact implements androidx.glance.appwidget.SizeMode {
+    field public static final androidx.glance.appwidget.SizeMode.Exact INSTANCE;
+  }
+
+  public static final class SizeMode.Responsive implements androidx.glance.appwidget.SizeMode {
+    ctor public SizeMode.Responsive(java.util.Set<androidx.compose.ui.unit.DpSize> sizes);
+    method public java.util.Set<androidx.compose.ui.unit.DpSize> getSizes();
+    property public final java.util.Set<androidx.compose.ui.unit.DpSize> sizes;
+  }
+
+  public static final class SizeMode.Single implements androidx.glance.appwidget.SizeMode {
+    field public static final androidx.glance.appwidget.SizeMode.Single INSTANCE;
+  }
+
+  public abstract sealed class SwitchColors {
+  }
+
+  public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.SwitchColors colors(androidx.glance.unit.ColorProvider checkedThumbColor, androidx.glance.unit.ColorProvider uncheckedThumbColor, androidx.glance.unit.ColorProvider checkedTrackColor, androidx.glance.unit.ColorProvider uncheckedTrackColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.SwitchColors colors();
+    field public static final androidx.glance.appwidget.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors, optional int maxLines);
+  }
+
+}
+
+package androidx.glance.appwidget.action {
+
+  public interface ActionCallback {
+    method public suspend Object? onAction(android.content.Context context, androidx.glance.GlanceId glanceId, androidx.glance.action.ActionParameters parameters, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
+  public final class RunCallbackActionKt {
+    method public static <T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action actionRunCallback(Class<T> callbackClass, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action actionRunCallback(optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class SendBroadcastActionKt {
+    method public static androidx.glance.action.Action actionSendBroadcast(String action, optional android.content.ComponentName? componentName);
+    method public static androidx.glance.action.Action actionSendBroadcast(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionSendBroadcast(android.content.ComponentName componentName);
+    method public static <T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionSendBroadcast(Class<T> receiver);
+    method public static inline <reified T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionSendBroadcast();
+  }
+
+  public final class StartActivityIntentActionKt {
+    method public static androidx.glance.action.Action actionStartActivity(android.content.Intent intent, optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class StartServiceActionKt {
+    method public static androidx.glance.action.Action actionStartService(android.content.Intent intent, optional boolean isForegroundService);
+    method public static androidx.glance.action.Action actionStartService(android.content.ComponentName componentName, optional boolean isForegroundService);
+    method public static <T extends android.app.Service> androidx.glance.action.Action actionStartService(Class<T> service, optional boolean isForegroundService);
+    method public static inline <reified T extends android.app.Service> androidx.glance.action.Action actionStartService(optional boolean isForegroundService);
+  }
+
+  public final class ToggleableKt {
+    method public static androidx.glance.action.ActionParameters.Key<java.lang.Boolean> getToggleableStateKey();
+    property public static final androidx.glance.action.ActionParameters.Key<java.lang.Boolean> ToggleableStateKey;
+  }
+
+}
+
+package androidx.glance.appwidget.lazy {
+
+  public abstract sealed class GridCells {
+  }
+
+  @RequiresApi(31) public static final class GridCells.Adaptive extends androidx.glance.appwidget.lazy.GridCells {
+    ctor public GridCells.Adaptive(float minSize);
+    method public float getMinSize();
+    property public final float minSize;
+  }
+
+  public static final class GridCells.Fixed extends androidx.glance.appwidget.lazy.GridCells {
+    ctor public GridCells.Fixed(int count);
+    method public int getCount();
+    property public final int count;
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker public interface LazyItemScope {
+  }
+
+  public final class LazyListKt {
+    method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyListScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyListScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyListScope, T![] items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyListScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyListScope, T![] items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker @kotlin.jvm.JvmDefaultWithCompatibility public interface LazyListScope {
+    method public void item(optional long itemId, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyItemScope,kotlin.Unit> content);
+    method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    field public static final androidx.glance.appwidget.lazy.LazyListScope.Companion Companion;
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  public static final class LazyListScope.Companion {
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  @kotlin.DslMarker public @interface LazyScopeMarker {
+  }
+
+  public final class LazyVerticalGridKt {
+    method @androidx.compose.runtime.Composable public static void LazyVerticalGrid(androidx.glance.appwidget.lazy.GridCells gridCells, optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyVerticalGridScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyVerticalGridScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyVerticalGridScope, T![] items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyVerticalGridScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyVerticalGridScope, T![] items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker @kotlin.jvm.JvmDefaultWithCompatibility public interface LazyVerticalGridScope {
+    method public void item(optional long itemId, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyItemScope,kotlin.Unit> content);
+    method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    field public static final androidx.glance.appwidget.lazy.LazyVerticalGridScope.Companion Companion;
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  public static final class LazyVerticalGridScope.Companion {
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+}
+
+package androidx.glance.appwidget.state {
+
+  public final class GlanceAppWidgetStateKt {
+    method public static suspend <T> Object? getAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend <T> Object? getAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend <T> Object? updateAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend Object? updateAppWidgetState(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super androidx.datastore.preferences.core.MutablePreferences,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> updateState, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
+}
+
diff --git a/glance/glance-appwidget/api/public_plus_experimental_1.0.0-beta01.txt b/glance/glance-appwidget/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..4ac3223
--- /dev/null
+++ b/glance/glance-appwidget/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,278 @@
+// Signature format: 4.0
+package androidx.glance.appwidget {
+
+  public final class AndroidRemoteViewsKt {
+    method @androidx.compose.runtime.Composable public static void AndroidRemoteViews(android.widget.RemoteViews remoteViews, optional androidx.glance.GlanceModifier modifier);
+    method @androidx.compose.runtime.Composable public static void AndroidRemoteViews(android.widget.RemoteViews remoteViews, @IdRes int containerViewId, optional androidx.glance.GlanceModifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class AppWidgetBackgroundKt {
+    method public static androidx.glance.GlanceModifier appWidgetBackground(androidx.glance.GlanceModifier);
+  }
+
+  public final class AppWidgetComposerKt {
+    method public static suspend Object? compose(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId id, optional android.os.Bundle? options, optional androidx.compose.ui.unit.DpSize? size, optional Object? state, optional kotlin.coroutines.Continuation<? super android.widget.RemoteViews>);
+  }
+
+  public final class BackgroundKt {
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, long day, long night);
+  }
+
+  public abstract sealed class CheckBoxColors {
+  }
+
+  public final class CheckBoxKt {
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors, optional int maxLines);
+  }
+
+  public final class CheckboxDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors(androidx.glance.unit.ColorProvider checkedColor, androidx.glance.unit.ColorProvider uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors(long checkedColor, long uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors();
+    field public static final androidx.glance.appwidget.CheckboxDefaults INSTANCE;
+  }
+
+  public final class CircularProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color);
+  }
+
+  public final class CompositionLocalsKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> getLocalAppWidgetOptions();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> LocalAppWidgetOptions;
+  }
+
+  public final class CornerRadiusKt {
+    method public static androidx.glance.GlanceModifier cornerRadius(androidx.glance.GlanceModifier, float radius);
+    method public static androidx.glance.GlanceModifier cornerRadius(androidx.glance.GlanceModifier, @DimenRes int radius);
+  }
+
+  @kotlin.RequiresOptIn(message="This API is experimental and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalGlanceRemoteViewsApi {
+  }
+
+  public abstract class GlanceAppWidget {
+    ctor public GlanceAppWidget(optional @LayoutRes int errorUiLayout);
+    method public androidx.glance.appwidget.SizeMode getSizeMode();
+    method public androidx.glance.state.GlanceStateDefinition<?>? getStateDefinition();
+    method public suspend Object? onDelete(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public abstract suspend Object? provideGlance(android.content.Context context, androidx.glance.GlanceId id, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final suspend Object? update(android.content.Context context, androidx.glance.GlanceId id, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public androidx.glance.appwidget.SizeMode sizeMode;
+    property public androidx.glance.state.GlanceStateDefinition<?>? stateDefinition;
+  }
+
+  public final class GlanceAppWidgetKt {
+    method public static suspend Object? provideContent(androidx.glance.appwidget.GlanceAppWidget, kotlin.jvm.functions.Function0<kotlin.Unit> content, kotlin.coroutines.Continuation<?>);
+    method public static suspend Object? updateAll(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static suspend inline <reified State> void updateIf(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.jvm.functions.Function1<? super State,? extends java.lang.Boolean> predicate);
+  }
+
+  public final class GlanceAppWidgetManager {
+    ctor public GlanceAppWidgetManager(android.content.Context context);
+    method public int getAppWidgetId(androidx.glance.GlanceId glanceId);
+    method public suspend Object? getAppWidgetSizes(androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.compose.ui.unit.DpSize>>);
+    method public androidx.glance.GlanceId getGlanceIdBy(int appWidgetId);
+    method public androidx.glance.GlanceId? getGlanceIdBy(android.content.Intent configurationIntent);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidget> Object? getGlanceIds(Class<T> provider, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.glance.GlanceId>>);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional Object? previewState, optional android.app.PendingIntent? successCallback, optional kotlin.coroutines.Continuation<? super java.lang.Boolean>);
+  }
+
+  public abstract class GlanceAppWidgetReceiver extends android.appwidget.AppWidgetProvider {
+    ctor public GlanceAppWidgetReceiver();
+    method public abstract androidx.glance.appwidget.GlanceAppWidget getGlanceAppWidget();
+    property public abstract androidx.glance.appwidget.GlanceAppWidget glanceAppWidget;
+    field public static final String ACTION_DEBUG_UPDATE = "androidx.glance.appwidget.action.DEBUG_UPDATE";
+    field public static final androidx.glance.appwidget.GlanceAppWidgetReceiver.Companion Companion;
+  }
+
+  public static final class GlanceAppWidgetReceiver.Companion {
+  }
+
+  @androidx.glance.appwidget.ExperimentalGlanceRemoteViewsApi public final class GlanceRemoteViews {
+    ctor public GlanceRemoteViews();
+    method public suspend Object? compose(android.content.Context context, long size, optional Object? state, optional android.os.Bundle appWidgetOptions, kotlin.jvm.functions.Function0<kotlin.Unit> content, kotlin.coroutines.Continuation<? super androidx.glance.appwidget.RemoteViewsCompositionResult>);
+  }
+
+  public final class ImageProvidersKt {
+    method public static androidx.glance.ImageProvider ImageProvider(android.net.Uri uri);
+  }
+
+  public final class LinearProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color, optional androidx.glance.unit.ColorProvider backgroundColor);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color, optional androidx.glance.unit.ColorProvider backgroundColor);
+  }
+
+  public final class ProgressIndicatorDefaults {
+    method public androidx.glance.unit.ColorProvider getBackgroundColorProvider();
+    method public androidx.glance.unit.ColorProvider getIndicatorColorProvider();
+    property public final androidx.glance.unit.ColorProvider BackgroundColorProvider;
+    property public final androidx.glance.unit.ColorProvider IndicatorColorProvider;
+    field public static final androidx.glance.appwidget.ProgressIndicatorDefaults INSTANCE;
+  }
+
+  public final class RadioButtonColors {
+  }
+
+  public final class RadioButtonDefaults {
+    method public androidx.glance.appwidget.RadioButtonColors colors(androidx.glance.unit.ColorProvider checkedColor, androidx.glance.unit.ColorProvider uncheckedColor);
+    method public androidx.glance.appwidget.RadioButtonColors colors(long checkedColor, long uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.RadioButtonColors colors();
+    field public static final androidx.glance.appwidget.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean checked, androidx.glance.action.Action? onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.RadioButtonColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.RadioButtonColors colors, optional int maxLines);
+    method public static androidx.glance.GlanceModifier selectableGroup(androidx.glance.GlanceModifier);
+  }
+
+  @androidx.glance.appwidget.ExperimentalGlanceRemoteViewsApi public final class RemoteViewsCompositionResult {
+    ctor public RemoteViewsCompositionResult(android.widget.RemoteViews remoteViews);
+    method public android.widget.RemoteViews getRemoteViews();
+    property public final android.widget.RemoteViews remoteViews;
+  }
+
+  public sealed interface SizeMode {
+  }
+
+  public static final class SizeMode.Exact implements androidx.glance.appwidget.SizeMode {
+    field public static final androidx.glance.appwidget.SizeMode.Exact INSTANCE;
+  }
+
+  public static final class SizeMode.Responsive implements androidx.glance.appwidget.SizeMode {
+    ctor public SizeMode.Responsive(java.util.Set<androidx.compose.ui.unit.DpSize> sizes);
+    method public java.util.Set<androidx.compose.ui.unit.DpSize> getSizes();
+    property public final java.util.Set<androidx.compose.ui.unit.DpSize> sizes;
+  }
+
+  public static final class SizeMode.Single implements androidx.glance.appwidget.SizeMode {
+    field public static final androidx.glance.appwidget.SizeMode.Single INSTANCE;
+  }
+
+  public abstract sealed class SwitchColors {
+  }
+
+  public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.SwitchColors colors(androidx.glance.unit.ColorProvider checkedThumbColor, androidx.glance.unit.ColorProvider uncheckedThumbColor, androidx.glance.unit.ColorProvider checkedTrackColor, androidx.glance.unit.ColorProvider uncheckedTrackColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.SwitchColors colors();
+    field public static final androidx.glance.appwidget.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors, optional int maxLines);
+  }
+
+}
+
+package androidx.glance.appwidget.action {
+
+  public interface ActionCallback {
+    method public suspend Object? onAction(android.content.Context context, androidx.glance.GlanceId glanceId, androidx.glance.action.ActionParameters parameters, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
+  public final class RunCallbackActionKt {
+    method public static <T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action actionRunCallback(Class<T> callbackClass, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action actionRunCallback(optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class SendBroadcastActionKt {
+    method public static androidx.glance.action.Action actionSendBroadcast(String action, optional android.content.ComponentName? componentName);
+    method public static androidx.glance.action.Action actionSendBroadcast(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionSendBroadcast(android.content.ComponentName componentName);
+    method public static <T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionSendBroadcast(Class<T> receiver);
+    method public static inline <reified T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionSendBroadcast();
+  }
+
+  public final class StartActivityIntentActionKt {
+    method public static androidx.glance.action.Action actionStartActivity(android.content.Intent intent, optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class StartServiceActionKt {
+    method public static androidx.glance.action.Action actionStartService(android.content.Intent intent, optional boolean isForegroundService);
+    method public static androidx.glance.action.Action actionStartService(android.content.ComponentName componentName, optional boolean isForegroundService);
+    method public static <T extends android.app.Service> androidx.glance.action.Action actionStartService(Class<T> service, optional boolean isForegroundService);
+    method public static inline <reified T extends android.app.Service> androidx.glance.action.Action actionStartService(optional boolean isForegroundService);
+  }
+
+  public final class ToggleableKt {
+    method public static androidx.glance.action.ActionParameters.Key<java.lang.Boolean> getToggleableStateKey();
+    property public static final androidx.glance.action.ActionParameters.Key<java.lang.Boolean> ToggleableStateKey;
+  }
+
+}
+
+package androidx.glance.appwidget.lazy {
+
+  public abstract sealed class GridCells {
+  }
+
+  @RequiresApi(31) public static final class GridCells.Adaptive extends androidx.glance.appwidget.lazy.GridCells {
+    ctor public GridCells.Adaptive(float minSize);
+    method public float getMinSize();
+    property public final float minSize;
+  }
+
+  public static final class GridCells.Fixed extends androidx.glance.appwidget.lazy.GridCells {
+    ctor public GridCells.Fixed(int count);
+    method public int getCount();
+    property public final int count;
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker public interface LazyItemScope {
+  }
+
+  public final class LazyListKt {
+    method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyListScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyListScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyListScope, T![] items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyListScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyListScope, T![] items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker @kotlin.jvm.JvmDefaultWithCompatibility public interface LazyListScope {
+    method public void item(optional long itemId, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyItemScope,kotlin.Unit> content);
+    method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    field public static final androidx.glance.appwidget.lazy.LazyListScope.Companion Companion;
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  public static final class LazyListScope.Companion {
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  @kotlin.DslMarker public @interface LazyScopeMarker {
+  }
+
+  public final class LazyVerticalGridKt {
+    method @androidx.compose.runtime.Composable public static void LazyVerticalGrid(androidx.glance.appwidget.lazy.GridCells gridCells, optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyVerticalGridScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyVerticalGridScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyVerticalGridScope, T![] items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyVerticalGridScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyVerticalGridScope, T![] items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker @kotlin.jvm.JvmDefaultWithCompatibility public interface LazyVerticalGridScope {
+    method public void item(optional long itemId, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyItemScope,kotlin.Unit> content);
+    method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    field public static final androidx.glance.appwidget.lazy.LazyVerticalGridScope.Companion Companion;
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  public static final class LazyVerticalGridScope.Companion {
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+}
+
+package androidx.glance.appwidget.state {
+
+  public final class GlanceAppWidgetStateKt {
+    method public static suspend <T> Object? getAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend <T> Object? getAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend <T> Object? updateAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend Object? updateAppWidgetState(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super androidx.datastore.preferences.core.MutablePreferences,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> updateState, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
+}
+
diff --git a/glance/glance-appwidget/api/res-1.0.0-beta01.txt b/glance/glance-appwidget/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..dba4906
--- /dev/null
+++ b/glance/glance-appwidget/api/res-1.0.0-beta01.txt
@@ -0,0 +1,2 @@
+bool glance_appwidget_available
+layout glance_default_loading_layout
diff --git a/glance/glance-appwidget/api/restricted_1.0.0-beta01.txt b/glance/glance-appwidget/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..72717d0
--- /dev/null
+++ b/glance/glance-appwidget/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,264 @@
+// Signature format: 4.0
+package androidx.glance.appwidget {
+
+  public final class AndroidRemoteViewsKt {
+    method @androidx.compose.runtime.Composable public static void AndroidRemoteViews(android.widget.RemoteViews remoteViews, optional androidx.glance.GlanceModifier modifier);
+    method @androidx.compose.runtime.Composable public static void AndroidRemoteViews(android.widget.RemoteViews remoteViews, @IdRes int containerViewId, optional androidx.glance.GlanceModifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class AppWidgetBackgroundKt {
+    method public static androidx.glance.GlanceModifier appWidgetBackground(androidx.glance.GlanceModifier);
+  }
+
+  public final class AppWidgetComposerKt {
+    method public static suspend Object? compose(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId id, optional android.os.Bundle? options, optional androidx.compose.ui.unit.DpSize? size, optional Object? state, optional kotlin.coroutines.Continuation<? super android.widget.RemoteViews>);
+  }
+
+  public final class BackgroundKt {
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, long day, long night);
+  }
+
+  public abstract sealed class CheckBoxColors {
+  }
+
+  public final class CheckBoxKt {
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors, optional int maxLines);
+  }
+
+  public final class CheckboxDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors(androidx.glance.unit.ColorProvider checkedColor, androidx.glance.unit.ColorProvider uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors(long checkedColor, long uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.CheckBoxColors colors();
+    field public static final androidx.glance.appwidget.CheckboxDefaults INSTANCE;
+  }
+
+  public final class CircularProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color);
+  }
+
+  public final class CompositionLocalsKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> getLocalAppWidgetOptions();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> LocalAppWidgetOptions;
+  }
+
+  public final class CornerRadiusKt {
+    method public static androidx.glance.GlanceModifier cornerRadius(androidx.glance.GlanceModifier, float radius);
+    method public static androidx.glance.GlanceModifier cornerRadius(androidx.glance.GlanceModifier, @DimenRes int radius);
+  }
+
+  public abstract class GlanceAppWidget {
+    ctor public GlanceAppWidget(optional @LayoutRes int errorUiLayout);
+    method public androidx.glance.appwidget.SizeMode getSizeMode();
+    method public androidx.glance.state.GlanceStateDefinition<?>? getStateDefinition();
+    method public suspend Object? onDelete(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public abstract suspend Object? provideGlance(android.content.Context context, androidx.glance.GlanceId id, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final suspend Object? update(android.content.Context context, androidx.glance.GlanceId id, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public androidx.glance.appwidget.SizeMode sizeMode;
+    property public androidx.glance.state.GlanceStateDefinition<?>? stateDefinition;
+  }
+
+  public final class GlanceAppWidgetKt {
+    method public static suspend Object? provideContent(androidx.glance.appwidget.GlanceAppWidget, kotlin.jvm.functions.Function0<kotlin.Unit> content, kotlin.coroutines.Continuation<?>);
+    method public static suspend Object? updateAll(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static suspend inline <reified State> void updateIf(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.jvm.functions.Function1<? super State,? extends java.lang.Boolean> predicate);
+  }
+
+  public final class GlanceAppWidgetManager {
+    ctor public GlanceAppWidgetManager(android.content.Context context);
+    method public int getAppWidgetId(androidx.glance.GlanceId glanceId);
+    method public suspend Object? getAppWidgetSizes(androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.compose.ui.unit.DpSize>>);
+    method public androidx.glance.GlanceId getGlanceIdBy(int appWidgetId);
+    method public androidx.glance.GlanceId? getGlanceIdBy(android.content.Intent configurationIntent);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidget> Object? getGlanceIds(Class<T> provider, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.glance.GlanceId>>);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional Object? previewState, optional android.app.PendingIntent? successCallback, optional kotlin.coroutines.Continuation<? super java.lang.Boolean>);
+  }
+
+  public abstract class GlanceAppWidgetReceiver extends android.appwidget.AppWidgetProvider {
+    ctor public GlanceAppWidgetReceiver();
+    method public abstract androidx.glance.appwidget.GlanceAppWidget getGlanceAppWidget();
+    property public abstract androidx.glance.appwidget.GlanceAppWidget glanceAppWidget;
+    field public static final String ACTION_DEBUG_UPDATE = "androidx.glance.appwidget.action.DEBUG_UPDATE";
+    field public static final androidx.glance.appwidget.GlanceAppWidgetReceiver.Companion Companion;
+  }
+
+  public static final class GlanceAppWidgetReceiver.Companion {
+  }
+
+  public final class ImageProvidersKt {
+    method public static androidx.glance.ImageProvider ImageProvider(android.net.Uri uri);
+  }
+
+  public final class LinearProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color, optional androidx.glance.unit.ColorProvider backgroundColor);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.unit.ColorProvider color, optional androidx.glance.unit.ColorProvider backgroundColor);
+  }
+
+  public final class ProgressIndicatorDefaults {
+    method public androidx.glance.unit.ColorProvider getBackgroundColorProvider();
+    method public androidx.glance.unit.ColorProvider getIndicatorColorProvider();
+    property public final androidx.glance.unit.ColorProvider BackgroundColorProvider;
+    property public final androidx.glance.unit.ColorProvider IndicatorColorProvider;
+    field public static final androidx.glance.appwidget.ProgressIndicatorDefaults INSTANCE;
+  }
+
+  public final class RadioButtonColors {
+  }
+
+  public final class RadioButtonDefaults {
+    method public androidx.glance.appwidget.RadioButtonColors colors(androidx.glance.unit.ColorProvider checkedColor, androidx.glance.unit.ColorProvider uncheckedColor);
+    method public androidx.glance.appwidget.RadioButtonColors colors(long checkedColor, long uncheckedColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.RadioButtonColors colors();
+    field public static final androidx.glance.appwidget.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean checked, androidx.glance.action.Action? onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.RadioButtonColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.RadioButtonColors colors, optional int maxLines);
+    method public static androidx.glance.GlanceModifier selectableGroup(androidx.glance.GlanceModifier);
+  }
+
+  public sealed interface SizeMode {
+  }
+
+  public static final class SizeMode.Exact implements androidx.glance.appwidget.SizeMode {
+    field public static final androidx.glance.appwidget.SizeMode.Exact INSTANCE;
+  }
+
+  public static final class SizeMode.Responsive implements androidx.glance.appwidget.SizeMode {
+    ctor public SizeMode.Responsive(java.util.Set<androidx.compose.ui.unit.DpSize> sizes);
+    method public java.util.Set<androidx.compose.ui.unit.DpSize> getSizes();
+    property public final java.util.Set<androidx.compose.ui.unit.DpSize> sizes;
+  }
+
+  public static final class SizeMode.Single implements androidx.glance.appwidget.SizeMode {
+    field public static final androidx.glance.appwidget.SizeMode.Single INSTANCE;
+  }
+
+  public abstract sealed class SwitchColors {
+  }
+
+  public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.SwitchColors colors(androidx.glance.unit.ColorProvider checkedThumbColor, androidx.glance.unit.ColorProvider uncheckedThumbColor, androidx.glance.unit.ColorProvider checkedTrackColor, androidx.glance.unit.ColorProvider uncheckedTrackColor);
+    method @androidx.compose.runtime.Composable public androidx.glance.appwidget.SwitchColors colors();
+    field public static final androidx.glance.appwidget.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function0<kotlin.Unit> onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors, optional int maxLines);
+  }
+
+}
+
+package androidx.glance.appwidget.action {
+
+  public interface ActionCallback {
+    method public suspend Object? onAction(android.content.Context context, androidx.glance.GlanceId glanceId, androidx.glance.action.ActionParameters parameters, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
+  public final class RunCallbackActionKt {
+    method public static <T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action actionRunCallback(Class<T> callbackClass, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action actionRunCallback(optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class SendBroadcastActionKt {
+    method public static androidx.glance.action.Action actionSendBroadcast(String action, optional android.content.ComponentName? componentName);
+    method public static androidx.glance.action.Action actionSendBroadcast(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionSendBroadcast(android.content.ComponentName componentName);
+    method public static <T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionSendBroadcast(Class<T> receiver);
+    method public static inline <reified T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionSendBroadcast();
+  }
+
+  public final class StartActivityIntentActionKt {
+    method public static androidx.glance.action.Action actionStartActivity(android.content.Intent intent, optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class StartServiceActionKt {
+    method public static androidx.glance.action.Action actionStartService(android.content.Intent intent, optional boolean isForegroundService);
+    method public static androidx.glance.action.Action actionStartService(android.content.ComponentName componentName, optional boolean isForegroundService);
+    method public static <T extends android.app.Service> androidx.glance.action.Action actionStartService(Class<T> service, optional boolean isForegroundService);
+    method public static inline <reified T extends android.app.Service> androidx.glance.action.Action actionStartService(optional boolean isForegroundService);
+  }
+
+  public final class ToggleableKt {
+    method public static androidx.glance.action.ActionParameters.Key<java.lang.Boolean> getToggleableStateKey();
+    property public static final androidx.glance.action.ActionParameters.Key<java.lang.Boolean> ToggleableStateKey;
+  }
+
+}
+
+package androidx.glance.appwidget.lazy {
+
+  public abstract sealed class GridCells {
+  }
+
+  @RequiresApi(31) public static final class GridCells.Adaptive extends androidx.glance.appwidget.lazy.GridCells {
+    ctor public GridCells.Adaptive(float minSize);
+    method public float getMinSize();
+    property public final float minSize;
+  }
+
+  public static final class GridCells.Fixed extends androidx.glance.appwidget.lazy.GridCells {
+    ctor public GridCells.Fixed(int count);
+    method public int getCount();
+    property public final int count;
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker public interface LazyItemScope {
+  }
+
+  public final class LazyListKt {
+    method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyListScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyListScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyListScope, T![] items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyListScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyListScope, T![] items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker @kotlin.jvm.JvmDefaultWithCompatibility public interface LazyListScope {
+    method public void item(optional long itemId, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyItemScope,kotlin.Unit> content);
+    method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    field public static final androidx.glance.appwidget.lazy.LazyListScope.Companion Companion;
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  public static final class LazyListScope.Companion {
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  @kotlin.DslMarker public @interface LazyScopeMarker {
+  }
+
+  public final class LazyVerticalGridKt {
+    method @androidx.compose.runtime.Composable public static void LazyVerticalGrid(androidx.glance.appwidget.lazy.GridCells gridCells, optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyVerticalGridScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyVerticalGridScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void items(androidx.glance.appwidget.lazy.LazyVerticalGridScope, T![] items, optional kotlin.jvm.functions.Function1<? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyVerticalGridScope, java.util.List<? extends T> items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsIndexed(androidx.glance.appwidget.lazy.LazyVerticalGridScope, T![] items, optional kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,java.lang.Long> itemId, kotlin.jvm.functions.Function3<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+  }
+
+  @androidx.glance.appwidget.lazy.LazyScopeMarker @kotlin.jvm.JvmDefaultWithCompatibility public interface LazyVerticalGridScope {
+    method public void item(optional long itemId, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.lazy.LazyItemScope,kotlin.Unit> content);
+    method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,java.lang.Long> itemId, kotlin.jvm.functions.Function2<? super androidx.glance.appwidget.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    field public static final androidx.glance.appwidget.lazy.LazyVerticalGridScope.Companion Companion;
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+  public static final class LazyVerticalGridScope.Companion {
+    field public static final long UnspecifiedItemId = -9223372036854775808L; // 0x8000000000000000L
+  }
+
+}
+
+package androidx.glance.appwidget.state {
+
+  public final class GlanceAppWidgetStateKt {
+    method public static suspend <T> Object? getAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend <T> Object? getAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend <T> Object? updateAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T>);
+    method public static suspend Object? updateAppWidgetState(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super androidx.datastore.preferences.core.MutablePreferences,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> updateState, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
+}
+
diff --git a/glance/glance-appwidget/build.gradle b/glance/glance-appwidget/build.gradle
index 3eaf94a..158c764 100644
--- a/glance/glance-appwidget/build.gradle
+++ b/glance/glance-appwidget/build.gradle
@@ -36,10 +36,7 @@
 AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */ false)
 
 dependencies {
-    bundleInside(project(
-            path: ":glance:glance-appwidget-proto",
-            configuration: "export"
-    ))
+    bundleInside(project(path: ":glance:glance-appwidget-proto", configuration: "export"))
 
     api(project(":glance:glance"))
     api("androidx.annotation:annotation:1.1.0")
@@ -73,6 +70,7 @@
 
     androidTestImplementation(project(":test:screenshot:screenshot"))
     androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
+    androidTestImplementation("androidx.room:room-runtime:2.4.3")
     androidTestImplementation('androidx.core:core-ktx:1.7.0')
     androidTestImplementation("androidx.work:work-testing:2.7.1")
     androidTestImplementation(libs.espressoCore)
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
index 2430d3f..01b903d 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
@@ -36,6 +36,7 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.UiDevice
 import androidx.work.WorkManager
+import androidx.work.impl.WorkManagerImpl
 import androidx.work.testing.WorkManagerTestInitHelper
 import com.google.common.truth.Truth.assertThat
 import java.lang.ref.WeakReference
@@ -111,6 +112,8 @@
                 mUiAutomation.dropShellPermissionIdentity()
             }
             WorkManager.getInstance(mContext).cancelAllWork()
+            // TODO(b/242026176): remove this once WorkManager allows closing the test database.
+            WorkManagerImpl.getInstance(context).workDatabase.close()
         }
     }
 
diff --git a/glance/glance-material/api/1.0.0-beta01.txt b/glance/glance-material/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..25d2aeb
--- /dev/null
+++ b/glance/glance-material/api/1.0.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.glance.material {
+
+  public final class MaterialThemesKt {
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material.Colors light, androidx.compose.material.Colors dark);
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material.Colors colors);
+  }
+
+}
+
diff --git a/glance/glance-material/api/public_plus_experimental_1.0.0-beta01.txt b/glance/glance-material/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..25d2aeb
--- /dev/null
+++ b/glance/glance-material/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.glance.material {
+
+  public final class MaterialThemesKt {
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material.Colors light, androidx.compose.material.Colors dark);
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material.Colors colors);
+  }
+
+}
+
diff --git a/glance/glance-material/api/res-1.0.0-beta01.txt b/glance/glance-material/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/glance/glance-material/api/res-1.0.0-beta01.txt
diff --git a/glance/glance-material/api/restricted_1.0.0-beta01.txt b/glance/glance-material/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..25d2aeb
--- /dev/null
+++ b/glance/glance-material/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.glance.material {
+
+  public final class MaterialThemesKt {
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material.Colors light, androidx.compose.material.Colors dark);
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material.Colors colors);
+  }
+
+}
+
diff --git a/glance/glance-material3/api/1.0.0-beta01.txt b/glance/glance-material3/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..8ff1aa6
--- /dev/null
+++ b/glance/glance-material3/api/1.0.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.glance.material3 {
+
+  public final class Material3ThemesKt {
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material3.ColorScheme light, androidx.compose.material3.ColorScheme dark);
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material3.ColorScheme scheme);
+  }
+
+}
+
diff --git a/glance/glance-material3/api/public_plus_experimental_1.0.0-beta01.txt b/glance/glance-material3/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..8ff1aa6
--- /dev/null
+++ b/glance/glance-material3/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.glance.material3 {
+
+  public final class Material3ThemesKt {
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material3.ColorScheme light, androidx.compose.material3.ColorScheme dark);
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material3.ColorScheme scheme);
+  }
+
+}
+
diff --git a/glance/glance-material3/api/res-1.0.0-beta01.txt b/glance/glance-material3/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/glance/glance-material3/api/res-1.0.0-beta01.txt
diff --git a/glance/glance-material3/api/restricted_1.0.0-beta01.txt b/glance/glance-material3/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..8ff1aa6
--- /dev/null
+++ b/glance/glance-material3/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.glance.material3 {
+
+  public final class Material3ThemesKt {
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material3.ColorScheme light, androidx.compose.material3.ColorScheme dark);
+    method public static androidx.glance.color.ColorProviders ColorProviders(androidx.compose.material3.ColorScheme scheme);
+  }
+
+}
+
diff --git a/glance/glance-preview/api/1.0.0-beta01.txt b/glance/glance-preview/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/glance/glance-preview/api/1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/glance/glance-preview/api/public_plus_experimental_1.0.0-beta01.txt b/glance/glance-preview/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..1fc4543
--- /dev/null
+++ b/glance/glance-preview/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,23 @@
+// Signature format: 4.0
+package androidx.glance.preview {
+
+  @kotlin.RequiresOptIn(message="This API is experimental and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalGlancePreviewApi {
+  }
+
+  @androidx.glance.preview.ExperimentalGlancePreviewApi @kotlin.annotation.Repeatable @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface GlancePreview {
+    method public abstract String surface();
+    property public abstract String surface;
+  }
+
+  @androidx.glance.preview.ExperimentalGlancePreviewApi @kotlin.annotation.Repeatable @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public static @interface GlancePreview.Container {
+    method public abstract androidx.glance.preview.GlancePreview[] value();
+  }
+
+  @androidx.glance.preview.ExperimentalGlancePreviewApi public final class Surfaces {
+    field public static final String APP_WIDGET = "AppWidget";
+    field public static final androidx.glance.preview.Surfaces INSTANCE;
+    field public static final String TILE = "Tile";
+  }
+
+}
+
diff --git a/glance/glance-preview/api/res-1.0.0-beta01.txt b/glance/glance-preview/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/glance/glance-preview/api/res-1.0.0-beta01.txt
diff --git a/glance/glance-preview/api/restricted_1.0.0-beta01.txt b/glance/glance-preview/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/glance/glance-preview/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/glance/glance-preview/build.gradle b/glance/glance-preview/build.gradle
index 61462cc..844dcee 100644
--- a/glance/glance-preview/build.gradle
+++ b/glance/glance-preview/build.gradle
@@ -26,6 +26,7 @@
 androidx {
     name = "Android Glance Preview"
     type = LibraryType.PUBLISHED_LIBRARY
+    mavenVersion = LibraryVersions.GLANCE_PREVIEW
     inceptionYear = "2022"
     description = "Glance preview library. This library provides the API required for marking the" +
             "glance @Composable components that should have preview in the Android Studio."
diff --git a/glance/glance-template/build.gradle b/glance/glance-template/build.gradle
index 1fd8868..a74f078 100644
--- a/glance/glance-template/build.gradle
+++ b/glance/glance-template/build.gradle
@@ -42,7 +42,6 @@
     implementation("androidx.work:work-runtime:2.7.1")
     implementation("androidx.work:work-runtime-ktx:2.7.1")
     implementation(libs.kotlinStdlib)
-    implementation(project(":compose:runtime:runtime"))
 
     // Force upgrade since 1.2.0 is not compatible with latest lint.
     implementation("androidx.annotation:annotation-experimental:1.3.0")
@@ -76,6 +75,7 @@
 androidx {
     name = "Glance Templates Library"
     type = LibraryType.PUBLISHED_LIBRARY
+    mavenVersion = LibraryVersions.GLANCE_TEMPLATE
     inceptionYear = "2021"
     description = "Glance allows developers to build layouts for remote surfaces using a Jetpack " +
             "Compose-style API."
diff --git a/glance/glance-wear-tiles-preview/build.gradle b/glance/glance-wear-tiles-preview/build.gradle
index 1736a49..a5836b4 100644
--- a/glance/glance-wear-tiles-preview/build.gradle
+++ b/glance/glance-wear-tiles-preview/build.gradle
@@ -53,6 +53,7 @@
 androidx {
     name = "Android Glance Wear Tiles Preview"
     type = LibraryType.PUBLISHED_LIBRARY
+    mavenVersion = LibraryVersions.GLANCE_WEAR_TILES
     inceptionYear = "2022"
     description = "Glance tooling library. This library provides the API required for the " +
             "GlanceTileService components and its Glance @Composable to be previewable in the IDE."
diff --git a/glance/glance-wear-tiles/build.gradle b/glance/glance-wear-tiles/build.gradle
index bcfb47e..155bfab 100644
--- a/glance/glance-wear-tiles/build.gradle
+++ b/glance/glance-wear-tiles/build.gradle
@@ -38,9 +38,8 @@
 
     implementation(libs.kotlinStdlib)
     implementation(libs.kotlinCoroutinesGuava)
-    implementation(projectOrArtifact(":lifecycle:lifecycle-runtime"))
-    implementation(projectOrArtifact(":lifecycle:lifecycle-runtime-ktx"))
-    implementation(projectOrArtifact(":lifecycle:lifecycle-service"))
+    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
+    implementation("androidx.lifecycle:lifecycle-service:2.6.1")
 
     testImplementation(libs.testCore)
     testImplementation(libs.testRules)
@@ -92,6 +91,7 @@
 androidx {
     name = "Glance for Wear Tiles"
     type = LibraryType.PUBLISHED_LIBRARY
+    mavenVersion = LibraryVersions.GLANCE_WEAR_TILES
     inceptionYear = "2021"
     description = "Glance allows developers to build layouts for Wear Tiles using a Jetpack " +
             "Compose-style API."
diff --git a/glance/glance/api/1.0.0-beta01.txt b/glance/glance/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..47d790f
--- /dev/null
+++ b/glance/glance/api/1.0.0-beta01.txt
@@ -0,0 +1,569 @@
+// Signature format: 4.0
+package androidx.glance {
+
+  public final class BackgroundKt {
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, long color);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, @ColorRes int color);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, androidx.glance.unit.ColorProvider colorProvider);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, androidx.glance.ImageProvider imageProvider, optional int contentScale);
+  }
+
+  public final class ButtonColors {
+    method public androidx.glance.unit.ColorProvider getBackgroundColor();
+    method public androidx.glance.unit.ColorProvider getContentColor();
+    property public final androidx.glance.unit.ColorProvider backgroundColor;
+    property public final androidx.glance.unit.ColorProvider contentColor;
+  }
+
+  public final class ButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.ButtonColors buttonColors(optional androidx.glance.unit.ColorProvider backgroundColor, optional androidx.glance.unit.ColorProvider contentColor);
+    field public static final androidx.glance.ButtonDefaults INSTANCE;
+  }
+
+  public final class ButtonKt {
+    method @androidx.compose.runtime.Composable public static void Button(String text, androidx.glance.action.Action onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional androidx.glance.text.TextStyle? style, optional androidx.glance.ButtonColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void Button(String text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional androidx.glance.text.TextStyle? style, optional androidx.glance.ButtonColors colors, optional int maxLines);
+  }
+
+  public final class ColorFilter {
+    field public static final androidx.glance.ColorFilter.Companion Companion;
+  }
+
+  public static final class ColorFilter.Companion {
+    method public androidx.glance.ColorFilter tint(androidx.glance.unit.ColorProvider colorProvider);
+  }
+
+  public final class CombinedGlanceModifier implements androidx.glance.GlanceModifier {
+    ctor public CombinedGlanceModifier(androidx.glance.GlanceModifier outer, androidx.glance.GlanceModifier inner);
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  public final class CompositionLocalsKt {
+    method @androidx.compose.runtime.Composable public static inline <reified T> T currentState();
+    method @androidx.compose.runtime.Composable public static inline <reified T> T? currentState(androidx.datastore.preferences.core.Preferences.Key<T> key);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<android.content.Context> getLocalContext();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.GlanceId> getLocalGlanceId();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.DpSize> getLocalSize();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Object> getLocalState();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.content.Context> LocalContext;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.GlanceId> LocalGlanceId;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.DpSize> LocalSize;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Object> LocalState;
+  }
+
+  @androidx.compose.runtime.ComposableTargetMarker(description="Glance Composable") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.FILE, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.TYPE, kotlin.annotation.AnnotationTarget.TYPE_PARAMETER}) public @interface GlanceComposable {
+  }
+
+  public interface GlanceId {
+  }
+
+  @androidx.compose.runtime.Stable @kotlin.jvm.JvmDefaultWithCompatibility public interface GlanceModifier {
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+    method public default infix androidx.glance.GlanceModifier then(androidx.glance.GlanceModifier other);
+    field public static final androidx.glance.GlanceModifier.Companion Companion;
+  }
+
+  public static final class GlanceModifier.Companion implements androidx.glance.GlanceModifier {
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public static interface GlanceModifier.Element extends androidx.glance.GlanceModifier {
+    method public default boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public default boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public default <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public default <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  public final class GlanceTheme {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable @androidx.glance.GlanceComposable public androidx.glance.color.ColorProviders getColors();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable @androidx.glance.GlanceComposable public final androidx.glance.color.ColorProviders colors;
+    field public static final androidx.glance.GlanceTheme INSTANCE;
+  }
+
+  public final class GlanceThemeKt {
+    method @androidx.compose.runtime.Composable public static void GlanceTheme(optional androidx.glance.color.ColorProviders colors, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ImageKt {
+    method @androidx.compose.runtime.Composable public static void Image(androidx.glance.ImageProvider provider, String? contentDescription, optional androidx.glance.GlanceModifier modifier, optional int contentScale, optional androidx.glance.ColorFilter? colorFilter);
+    method public static androidx.glance.ImageProvider ImageProvider(@DrawableRes int resId);
+    method public static androidx.glance.ImageProvider ImageProvider(android.graphics.Bitmap bitmap);
+    method @RequiresApi(android.os.Build.VERSION_CODES.M) public static androidx.glance.ImageProvider ImageProvider(android.graphics.drawable.Icon icon);
+  }
+
+  public interface ImageProvider {
+  }
+
+  public enum Visibility {
+    method public static androidx.glance.Visibility valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.glance.Visibility[] values();
+    enum_constant public static final androidx.glance.Visibility Gone;
+    enum_constant public static final androidx.glance.Visibility Invisible;
+    enum_constant public static final androidx.glance.Visibility Visible;
+  }
+
+  public final class VisibilityKt {
+    method public static androidx.glance.GlanceModifier visibility(androidx.glance.GlanceModifier, androidx.glance.Visibility visibility);
+  }
+
+}
+
+package androidx.glance.action {
+
+  public interface Action {
+  }
+
+  public final class ActionKt {
+    method public static androidx.glance.GlanceModifier clickable(androidx.glance.GlanceModifier, androidx.glance.action.Action onClick);
+    method @androidx.compose.runtime.Composable public static androidx.glance.GlanceModifier clickable(androidx.glance.GlanceModifier, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+  public abstract class ActionParameters {
+    method public abstract java.util.Map<androidx.glance.action.ActionParameters.Key<?>,java.lang.Object> asMap();
+    method public abstract operator <T> boolean contains(androidx.glance.action.ActionParameters.Key<T> key);
+    method public abstract operator <T> T? get(androidx.glance.action.ActionParameters.Key<T> key);
+    method public abstract <T> T getOrDefault(androidx.glance.action.ActionParameters.Key<T> key, T defaultValue);
+    method public abstract boolean isEmpty();
+  }
+
+  public static final class ActionParameters.Key<T> {
+    ctor public ActionParameters.Key(String name);
+    method public String getName();
+    method public infix androidx.glance.action.ActionParameters.Pair<T> to(T value);
+    property public final String name;
+  }
+
+  public static final class ActionParameters.Pair<T> {
+  }
+
+  public final class ActionParametersKt {
+    method public static androidx.glance.action.ActionParameters actionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
+    method public static androidx.glance.action.MutableActionParameters mutableActionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
+    method public static androidx.glance.action.MutableActionParameters toMutableParameters(androidx.glance.action.ActionParameters);
+    method public static androidx.glance.action.ActionParameters toParameters(androidx.glance.action.ActionParameters);
+    method public static <T> androidx.glance.action.ActionParameters.Key<T> toParametersKey(androidx.datastore.preferences.core.Preferences.Key<T>);
+  }
+
+  public final class LambdaActionKt {
+    method @androidx.compose.runtime.Composable public static androidx.glance.action.Action action(optional String? key, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+  public final class MutableActionParameters extends androidx.glance.action.ActionParameters {
+    method public java.util.Map<androidx.glance.action.ActionParameters.Key<?>,java.lang.Object> asMap();
+    method public void clear();
+    method public operator <T> boolean contains(androidx.glance.action.ActionParameters.Key<T> key);
+    method public operator <T> T? get(androidx.glance.action.ActionParameters.Key<T> key);
+    method public <T> T getOrDefault(androidx.glance.action.ActionParameters.Key<T> key, T defaultValue);
+    method public boolean isEmpty();
+    method public <T> T? remove(androidx.glance.action.ActionParameters.Key<T> key);
+    method public operator <T> T? set(androidx.glance.action.ActionParameters.Key<T> key, T? value);
+  }
+
+  public final class StartActivityActionKt {
+    method public static androidx.glance.action.Action actionStartActivity(android.content.ComponentName componentName, optional androidx.glance.action.ActionParameters parameters);
+    method public static <T extends android.app.Activity> androidx.glance.action.Action actionStartActivity(Class<T> activity, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action actionStartActivity(optional androidx.glance.action.ActionParameters parameters);
+  }
+
+}
+
+package androidx.glance.color {
+
+  public abstract sealed class ColorProviders {
+    method public final androidx.glance.unit.ColorProvider getBackground();
+    method public final androidx.glance.unit.ColorProvider getError();
+    method public final androidx.glance.unit.ColorProvider getErrorContainer();
+    method public final androidx.glance.unit.ColorProvider getInverseOnSurface();
+    method public final androidx.glance.unit.ColorProvider getInversePrimary();
+    method public final androidx.glance.unit.ColorProvider getInverseSurface();
+    method public final androidx.glance.unit.ColorProvider getOnBackground();
+    method public final androidx.glance.unit.ColorProvider getOnError();
+    method public final androidx.glance.unit.ColorProvider getOnErrorContainer();
+    method public final androidx.glance.unit.ColorProvider getOnPrimary();
+    method public final androidx.glance.unit.ColorProvider getOnPrimaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOnSecondary();
+    method public final androidx.glance.unit.ColorProvider getOnSecondaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOnSurface();
+    method public final androidx.glance.unit.ColorProvider getOnSurfaceVariant();
+    method public final androidx.glance.unit.ColorProvider getOnTertiary();
+    method public final androidx.glance.unit.ColorProvider getOnTertiaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOutline();
+    method public final androidx.glance.unit.ColorProvider getPrimary();
+    method public final androidx.glance.unit.ColorProvider getPrimaryContainer();
+    method public final androidx.glance.unit.ColorProvider getSecondary();
+    method public final androidx.glance.unit.ColorProvider getSecondaryContainer();
+    method public final androidx.glance.unit.ColorProvider getSurface();
+    method public final androidx.glance.unit.ColorProvider getSurfaceVariant();
+    method public final androidx.glance.unit.ColorProvider getTertiary();
+    method public final androidx.glance.unit.ColorProvider getTertiaryContainer();
+    property public final androidx.glance.unit.ColorProvider background;
+    property public final androidx.glance.unit.ColorProvider error;
+    property public final androidx.glance.unit.ColorProvider errorContainer;
+    property public final androidx.glance.unit.ColorProvider inverseOnSurface;
+    property public final androidx.glance.unit.ColorProvider inversePrimary;
+    property public final androidx.glance.unit.ColorProvider inverseSurface;
+    property public final androidx.glance.unit.ColorProvider onBackground;
+    property public final androidx.glance.unit.ColorProvider onError;
+    property public final androidx.glance.unit.ColorProvider onErrorContainer;
+    property public final androidx.glance.unit.ColorProvider onPrimary;
+    property public final androidx.glance.unit.ColorProvider onPrimaryContainer;
+    property public final androidx.glance.unit.ColorProvider onSecondary;
+    property public final androidx.glance.unit.ColorProvider onSecondaryContainer;
+    property public final androidx.glance.unit.ColorProvider onSurface;
+    property public final androidx.glance.unit.ColorProvider onSurfaceVariant;
+    property public final androidx.glance.unit.ColorProvider onTertiary;
+    property public final androidx.glance.unit.ColorProvider onTertiaryContainer;
+    property public final androidx.glance.unit.ColorProvider outline;
+    property public final androidx.glance.unit.ColorProvider primary;
+    property public final androidx.glance.unit.ColorProvider primaryContainer;
+    property public final androidx.glance.unit.ColorProvider secondary;
+    property public final androidx.glance.unit.ColorProvider secondaryContainer;
+    property public final androidx.glance.unit.ColorProvider surface;
+    property public final androidx.glance.unit.ColorProvider surfaceVariant;
+    property public final androidx.glance.unit.ColorProvider tertiary;
+    property public final androidx.glance.unit.ColorProvider tertiaryContainer;
+  }
+
+  public final class ColorProvidersKt {
+    method public static androidx.glance.color.ColorProviders colorProviders(androidx.glance.unit.ColorProvider primary, androidx.glance.unit.ColorProvider onPrimary, androidx.glance.unit.ColorProvider primaryContainer, androidx.glance.unit.ColorProvider onPrimaryContainer, androidx.glance.unit.ColorProvider secondary, androidx.glance.unit.ColorProvider onSecondary, androidx.glance.unit.ColorProvider secondaryContainer, androidx.glance.unit.ColorProvider onSecondaryContainer, androidx.glance.unit.ColorProvider tertiary, androidx.glance.unit.ColorProvider onTertiary, androidx.glance.unit.ColorProvider tertiaryContainer, androidx.glance.unit.ColorProvider onTertiaryContainer, androidx.glance.unit.ColorProvider error, androidx.glance.unit.ColorProvider errorContainer, androidx.glance.unit.ColorProvider onError, androidx.glance.unit.ColorProvider onErrorContainer, androidx.glance.unit.ColorProvider background, androidx.glance.unit.ColorProvider onBackground, androidx.glance.unit.ColorProvider surface, androidx.glance.unit.ColorProvider onSurface, androidx.glance.unit.ColorProvider surfaceVariant, androidx.glance.unit.ColorProvider onSurfaceVariant, androidx.glance.unit.ColorProvider outline, androidx.glance.unit.ColorProvider inverseOnSurface, androidx.glance.unit.ColorProvider inverseSurface, androidx.glance.unit.ColorProvider inversePrimary);
+  }
+
+  public final class DayNightColorProvidersKt {
+    method public static androidx.glance.unit.ColorProvider ColorProvider(long day, long night);
+  }
+
+}
+
+package androidx.glance.layout {
+
+  public final class Alignment {
+    ctor public Alignment(int horizontal, int vertical);
+    method public int getHorizontal();
+    method public int getVertical();
+    property public final int horizontal;
+    property public final int vertical;
+    field public static final androidx.glance.layout.Alignment.Companion Companion;
+  }
+
+  public static final class Alignment.Companion {
+    method public int getBottom();
+    method public androidx.glance.layout.Alignment getBottomCenter();
+    method public androidx.glance.layout.Alignment getBottomEnd();
+    method public androidx.glance.layout.Alignment getBottomStart();
+    method public androidx.glance.layout.Alignment getCenter();
+    method public androidx.glance.layout.Alignment getCenterEnd();
+    method public int getCenterHorizontally();
+    method public androidx.glance.layout.Alignment getCenterStart();
+    method public int getCenterVertically();
+    method public int getEnd();
+    method public int getStart();
+    method public int getTop();
+    method public androidx.glance.layout.Alignment getTopCenter();
+    method public androidx.glance.layout.Alignment getTopEnd();
+    method public androidx.glance.layout.Alignment getTopStart();
+    property public final int Bottom;
+    property public final androidx.glance.layout.Alignment BottomCenter;
+    property public final androidx.glance.layout.Alignment BottomEnd;
+    property public final androidx.glance.layout.Alignment BottomStart;
+    property public final androidx.glance.layout.Alignment Center;
+    property public final androidx.glance.layout.Alignment CenterEnd;
+    property public final int CenterHorizontally;
+    property public final androidx.glance.layout.Alignment CenterStart;
+    property public final int CenterVertically;
+    property public final int End;
+    property public final int Start;
+    property public final int Top;
+    property public final androidx.glance.layout.Alignment TopCenter;
+    property public final androidx.glance.layout.Alignment TopEnd;
+    property public final androidx.glance.layout.Alignment TopStart;
+  }
+
+  @kotlin.jvm.JvmInline public static final value class Alignment.Horizontal {
+    field public static final androidx.glance.layout.Alignment.Horizontal.Companion Companion;
+  }
+
+  public static final class Alignment.Horizontal.Companion {
+    method public int getCenterHorizontally();
+    method public int getEnd();
+    method public int getStart();
+    property public final int CenterHorizontally;
+    property public final int End;
+    property public final int Start;
+  }
+
+  @kotlin.jvm.JvmInline public static final value class Alignment.Vertical {
+    field public static final androidx.glance.layout.Alignment.Vertical.Companion Companion;
+  }
+
+  public static final class Alignment.Vertical.Companion {
+    method public int getBottom();
+    method public int getCenterVertically();
+    method public int getTop();
+    property public final int Bottom;
+    property public final int CenterVertically;
+    property public final int Top;
+  }
+
+  public final class BoxKt {
+    method @androidx.compose.runtime.Composable public static void Box(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.layout.Alignment contentAlignment, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ColumnKt {
+    method @androidx.compose.runtime.Composable public static void Column(optional androidx.glance.GlanceModifier modifier, optional int verticalAlignment, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  public interface ColumnScope {
+    method public androidx.glance.GlanceModifier defaultWeight(androidx.glance.GlanceModifier);
+  }
+
+  @kotlin.jvm.JvmInline public final value class ContentScale {
+    ctor public ContentScale(int value);
+    field public static final androidx.glance.layout.ContentScale.Companion Companion;
+  }
+
+  public static final class ContentScale.Companion {
+    method public int getCrop();
+    method public int getFillBounds();
+    method public int getFit();
+    property public final int Crop;
+    property public final int FillBounds;
+    property public final int Fit;
+  }
+
+  public final class PaddingKt {
+    method public static androidx.glance.GlanceModifier absolutePadding(androidx.glance.GlanceModifier, optional float left, optional float top, optional float right, optional float bottom);
+    method public static androidx.glance.GlanceModifier absolutePadding(androidx.glance.GlanceModifier, optional @DimenRes int left, optional @DimenRes int top, optional @DimenRes int right, optional @DimenRes int bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional float start, optional float top, optional float end, optional float bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional @DimenRes int start, optional @DimenRes int top, optional @DimenRes int end, optional @DimenRes int bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional float horizontal, optional float vertical);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional @DimenRes int horizontal, optional @DimenRes int vertical);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, float all);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, @DimenRes int all);
+  }
+
+  public final class RowKt {
+    method @androidx.compose.runtime.Composable public static void Row(optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, optional int verticalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.layout.RowScope,kotlin.Unit> content);
+  }
+
+  public interface RowScope {
+    method public androidx.glance.GlanceModifier defaultWeight(androidx.glance.GlanceModifier);
+  }
+
+  public final class SizeModifiersKt {
+    method public static androidx.glance.GlanceModifier fillMaxHeight(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier fillMaxSize(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier fillMaxWidth(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier height(androidx.glance.GlanceModifier, float height);
+    method public static androidx.glance.GlanceModifier height(androidx.glance.GlanceModifier, @DimenRes int height);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, float size);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, @DimenRes int size);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, float width, float height);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, @DimenRes int width, @DimenRes int height);
+    method public static androidx.glance.GlanceModifier width(androidx.glance.GlanceModifier, float width);
+    method public static androidx.glance.GlanceModifier width(androidx.glance.GlanceModifier, @DimenRes int width);
+    method public static androidx.glance.GlanceModifier wrapContentHeight(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier wrapContentSize(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier wrapContentWidth(androidx.glance.GlanceModifier);
+  }
+
+  public final class SpacerKt {
+    method @androidx.compose.runtime.Composable public static void Spacer(optional androidx.glance.GlanceModifier modifier);
+  }
+
+}
+
+package androidx.glance.semantics {
+
+  public final class SemanticsConfiguration implements androidx.glance.semantics.SemanticsPropertyReceiver {
+    ctor public SemanticsConfiguration();
+    method public operator <T> T get(androidx.glance.semantics.SemanticsPropertyKey<T> key);
+    method public <T> T? getOrElseNullable(androidx.glance.semantics.SemanticsPropertyKey<T> key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+    method public <T> T? getOrNull(androidx.glance.semantics.SemanticsPropertyKey<T> key);
+    method public <T> void set(androidx.glance.semantics.SemanticsPropertyKey<T> key, T value);
+  }
+
+  public final class SemanticsModifierKt {
+    method public static androidx.glance.GlanceModifier semantics(androidx.glance.GlanceModifier, kotlin.jvm.functions.Function1<? super androidx.glance.semantics.SemanticsPropertyReceiver,kotlin.Unit> properties);
+  }
+
+  public final class SemanticsProperties {
+    method public androidx.glance.semantics.SemanticsPropertyKey<java.util.List<java.lang.String>> getContentDescription();
+    property public final androidx.glance.semantics.SemanticsPropertyKey<java.util.List<java.lang.String>> ContentDescription;
+    field public static final androidx.glance.semantics.SemanticsProperties INSTANCE;
+  }
+
+  public final class SemanticsPropertiesKt {
+    method public static String getContentDescription(androidx.glance.semantics.SemanticsPropertyReceiver);
+    method public static void setContentDescription(androidx.glance.semantics.SemanticsPropertyReceiver, String);
+  }
+
+  public final class SemanticsPropertyKey<T> {
+    ctor public SemanticsPropertyKey(String name, optional kotlin.jvm.functions.Function2<? super T,? super T,? extends T> mergePolicy);
+    method public String getName();
+    method public T? merge(T? parentValue, T childValue);
+    property public final String name;
+  }
+
+  public interface SemanticsPropertyReceiver {
+    method public operator <T> void set(androidx.glance.semantics.SemanticsPropertyKey<T> key, T value);
+  }
+
+}
+
+package androidx.glance.session {
+
+  public final class SessionManagerKt {
+  }
+
+}
+
+package androidx.glance.state {
+
+  public interface GlanceStateDefinition<T> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>>);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
+  }
+
+  public final class PreferencesGlanceStateDefinition implements androidx.glance.state.GlanceStateDefinition<androidx.datastore.preferences.core.Preferences> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<androidx.datastore.preferences.core.Preferences>>);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
+    field public static final androidx.glance.state.PreferencesGlanceStateDefinition INSTANCE;
+  }
+
+}
+
+package androidx.glance.text {
+
+  public final class FontFamily {
+    ctor public FontFamily(String family);
+    method public String getFamily();
+    property public final String family;
+    field public static final androidx.glance.text.FontFamily.Companion Companion;
+  }
+
+  public static final class FontFamily.Companion {
+    method public androidx.glance.text.FontFamily getCursive();
+    method public androidx.glance.text.FontFamily getMonospace();
+    method public androidx.glance.text.FontFamily getSansSerif();
+    method public androidx.glance.text.FontFamily getSerif();
+    property public final androidx.glance.text.FontFamily Cursive;
+    property public final androidx.glance.text.FontFamily Monospace;
+    property public final androidx.glance.text.FontFamily SansSerif;
+    property public final androidx.glance.text.FontFamily Serif;
+  }
+
+  @kotlin.jvm.JvmInline public final value class FontStyle {
+    field public static final androidx.glance.text.FontStyle.Companion Companion;
+  }
+
+  public static final class FontStyle.Companion {
+    method public int getItalic();
+    method public int getNormal();
+    method public java.util.List<androidx.glance.text.FontStyle> values();
+    property public final int Italic;
+    property public final int Normal;
+  }
+
+  @kotlin.jvm.JvmInline public final value class FontWeight {
+    method public int getValue();
+    property public final int value;
+    field public static final androidx.glance.text.FontWeight.Companion Companion;
+  }
+
+  public static final class FontWeight.Companion {
+    method public int getBold();
+    method public int getMedium();
+    method public int getNormal();
+    property public final int Bold;
+    property public final int Medium;
+    property public final int Normal;
+  }
+
+  @kotlin.jvm.JvmInline public final value class TextAlign {
+    field public static final androidx.glance.text.TextAlign.Companion Companion;
+  }
+
+  public static final class TextAlign.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    method public int getLeft();
+    method public int getRight();
+    method public int getStart();
+    method public java.util.List<androidx.glance.text.TextAlign> values();
+    property public final int Center;
+    property public final int End;
+    property public final int Left;
+    property public final int Right;
+    property public final int Start;
+  }
+
+  @kotlin.jvm.JvmInline public final value class TextDecoration {
+    method @androidx.compose.runtime.Stable public operator boolean contains(int other);
+    method @androidx.compose.runtime.Stable public operator int plus(int decoration);
+    field public static final androidx.glance.text.TextDecoration.Companion Companion;
+  }
+
+  public static final class TextDecoration.Companion {
+    method public int combine(java.util.List<androidx.glance.text.TextDecoration> decorations);
+    method public int getLineThrough();
+    method public int getNone();
+    method public int getUnderline();
+    property public final int LineThrough;
+    property public final int None;
+    property public final int Underline;
+  }
+
+  public final class TextDefaults {
+    method public androidx.glance.unit.ColorProvider getDefaultTextColor();
+    method public androidx.glance.text.TextStyle getDefaultTextStyle();
+    property public final androidx.glance.unit.ColorProvider defaultTextColor;
+    property public final androidx.glance.text.TextStyle defaultTextStyle;
+    field public static final androidx.glance.text.TextDefaults INSTANCE;
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.glance.GlanceModifier modifier, optional androidx.glance.text.TextStyle style, optional int maxLines);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextStyle {
+    ctor public TextStyle(optional androidx.glance.unit.ColorProvider color, optional androidx.compose.ui.unit.TextUnit? fontSize, optional androidx.glance.text.FontWeight? fontWeight, optional androidx.glance.text.FontStyle? fontStyle, optional androidx.glance.text.TextAlign? textAlign, optional androidx.glance.text.TextDecoration? textDecoration, optional androidx.glance.text.FontFamily? fontFamily);
+    method public androidx.glance.text.TextStyle copy(optional androidx.glance.unit.ColorProvider color, optional androidx.compose.ui.unit.TextUnit? fontSize, optional androidx.glance.text.FontWeight? fontWeight, optional androidx.glance.text.FontStyle? fontStyle, optional androidx.glance.text.TextAlign? textAlign, optional androidx.glance.text.TextDecoration? textDecoration, optional androidx.glance.text.FontFamily? fontFamily);
+    method public androidx.glance.unit.ColorProvider getColor();
+    method public androidx.glance.text.FontFamily? getFontFamily();
+    method public androidx.compose.ui.unit.TextUnit? getFontSize();
+    method public androidx.glance.text.FontStyle? getFontStyle();
+    method public androidx.glance.text.FontWeight? getFontWeight();
+    method public androidx.glance.text.TextAlign? getTextAlign();
+    method public androidx.glance.text.TextDecoration? getTextDecoration();
+    property public final androidx.glance.unit.ColorProvider color;
+    property public final androidx.glance.text.FontFamily? fontFamily;
+    property public final androidx.compose.ui.unit.TextUnit? fontSize;
+    property public final androidx.glance.text.FontStyle? fontStyle;
+    property public final androidx.glance.text.FontWeight? fontWeight;
+    property public final androidx.glance.text.TextAlign? textAlign;
+    property public final androidx.glance.text.TextDecoration? textDecoration;
+  }
+
+}
+
+package androidx.glance.unit {
+
+  public interface ColorProvider {
+    method public long getColor(android.content.Context context);
+  }
+
+  public final class ColorProviderKt {
+    method public static androidx.glance.unit.ColorProvider ColorProvider(long color);
+  }
+
+}
+
diff --git a/glance/glance/api/public_plus_experimental_1.0.0-beta01.txt b/glance/glance/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..47d790f
--- /dev/null
+++ b/glance/glance/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,569 @@
+// Signature format: 4.0
+package androidx.glance {
+
+  public final class BackgroundKt {
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, long color);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, @ColorRes int color);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, androidx.glance.unit.ColorProvider colorProvider);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, androidx.glance.ImageProvider imageProvider, optional int contentScale);
+  }
+
+  public final class ButtonColors {
+    method public androidx.glance.unit.ColorProvider getBackgroundColor();
+    method public androidx.glance.unit.ColorProvider getContentColor();
+    property public final androidx.glance.unit.ColorProvider backgroundColor;
+    property public final androidx.glance.unit.ColorProvider contentColor;
+  }
+
+  public final class ButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.ButtonColors buttonColors(optional androidx.glance.unit.ColorProvider backgroundColor, optional androidx.glance.unit.ColorProvider contentColor);
+    field public static final androidx.glance.ButtonDefaults INSTANCE;
+  }
+
+  public final class ButtonKt {
+    method @androidx.compose.runtime.Composable public static void Button(String text, androidx.glance.action.Action onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional androidx.glance.text.TextStyle? style, optional androidx.glance.ButtonColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void Button(String text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional androidx.glance.text.TextStyle? style, optional androidx.glance.ButtonColors colors, optional int maxLines);
+  }
+
+  public final class ColorFilter {
+    field public static final androidx.glance.ColorFilter.Companion Companion;
+  }
+
+  public static final class ColorFilter.Companion {
+    method public androidx.glance.ColorFilter tint(androidx.glance.unit.ColorProvider colorProvider);
+  }
+
+  public final class CombinedGlanceModifier implements androidx.glance.GlanceModifier {
+    ctor public CombinedGlanceModifier(androidx.glance.GlanceModifier outer, androidx.glance.GlanceModifier inner);
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  public final class CompositionLocalsKt {
+    method @androidx.compose.runtime.Composable public static inline <reified T> T currentState();
+    method @androidx.compose.runtime.Composable public static inline <reified T> T? currentState(androidx.datastore.preferences.core.Preferences.Key<T> key);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<android.content.Context> getLocalContext();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.GlanceId> getLocalGlanceId();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.DpSize> getLocalSize();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Object> getLocalState();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.content.Context> LocalContext;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.GlanceId> LocalGlanceId;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.DpSize> LocalSize;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Object> LocalState;
+  }
+
+  @androidx.compose.runtime.ComposableTargetMarker(description="Glance Composable") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.FILE, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.TYPE, kotlin.annotation.AnnotationTarget.TYPE_PARAMETER}) public @interface GlanceComposable {
+  }
+
+  public interface GlanceId {
+  }
+
+  @androidx.compose.runtime.Stable @kotlin.jvm.JvmDefaultWithCompatibility public interface GlanceModifier {
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+    method public default infix androidx.glance.GlanceModifier then(androidx.glance.GlanceModifier other);
+    field public static final androidx.glance.GlanceModifier.Companion Companion;
+  }
+
+  public static final class GlanceModifier.Companion implements androidx.glance.GlanceModifier {
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public static interface GlanceModifier.Element extends androidx.glance.GlanceModifier {
+    method public default boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public default boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public default <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public default <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  public final class GlanceTheme {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable @androidx.glance.GlanceComposable public androidx.glance.color.ColorProviders getColors();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable @androidx.glance.GlanceComposable public final androidx.glance.color.ColorProviders colors;
+    field public static final androidx.glance.GlanceTheme INSTANCE;
+  }
+
+  public final class GlanceThemeKt {
+    method @androidx.compose.runtime.Composable public static void GlanceTheme(optional androidx.glance.color.ColorProviders colors, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ImageKt {
+    method @androidx.compose.runtime.Composable public static void Image(androidx.glance.ImageProvider provider, String? contentDescription, optional androidx.glance.GlanceModifier modifier, optional int contentScale, optional androidx.glance.ColorFilter? colorFilter);
+    method public static androidx.glance.ImageProvider ImageProvider(@DrawableRes int resId);
+    method public static androidx.glance.ImageProvider ImageProvider(android.graphics.Bitmap bitmap);
+    method @RequiresApi(android.os.Build.VERSION_CODES.M) public static androidx.glance.ImageProvider ImageProvider(android.graphics.drawable.Icon icon);
+  }
+
+  public interface ImageProvider {
+  }
+
+  public enum Visibility {
+    method public static androidx.glance.Visibility valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.glance.Visibility[] values();
+    enum_constant public static final androidx.glance.Visibility Gone;
+    enum_constant public static final androidx.glance.Visibility Invisible;
+    enum_constant public static final androidx.glance.Visibility Visible;
+  }
+
+  public final class VisibilityKt {
+    method public static androidx.glance.GlanceModifier visibility(androidx.glance.GlanceModifier, androidx.glance.Visibility visibility);
+  }
+
+}
+
+package androidx.glance.action {
+
+  public interface Action {
+  }
+
+  public final class ActionKt {
+    method public static androidx.glance.GlanceModifier clickable(androidx.glance.GlanceModifier, androidx.glance.action.Action onClick);
+    method @androidx.compose.runtime.Composable public static androidx.glance.GlanceModifier clickable(androidx.glance.GlanceModifier, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+  public abstract class ActionParameters {
+    method public abstract java.util.Map<androidx.glance.action.ActionParameters.Key<?>,java.lang.Object> asMap();
+    method public abstract operator <T> boolean contains(androidx.glance.action.ActionParameters.Key<T> key);
+    method public abstract operator <T> T? get(androidx.glance.action.ActionParameters.Key<T> key);
+    method public abstract <T> T getOrDefault(androidx.glance.action.ActionParameters.Key<T> key, T defaultValue);
+    method public abstract boolean isEmpty();
+  }
+
+  public static final class ActionParameters.Key<T> {
+    ctor public ActionParameters.Key(String name);
+    method public String getName();
+    method public infix androidx.glance.action.ActionParameters.Pair<T> to(T value);
+    property public final String name;
+  }
+
+  public static final class ActionParameters.Pair<T> {
+  }
+
+  public final class ActionParametersKt {
+    method public static androidx.glance.action.ActionParameters actionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
+    method public static androidx.glance.action.MutableActionParameters mutableActionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
+    method public static androidx.glance.action.MutableActionParameters toMutableParameters(androidx.glance.action.ActionParameters);
+    method public static androidx.glance.action.ActionParameters toParameters(androidx.glance.action.ActionParameters);
+    method public static <T> androidx.glance.action.ActionParameters.Key<T> toParametersKey(androidx.datastore.preferences.core.Preferences.Key<T>);
+  }
+
+  public final class LambdaActionKt {
+    method @androidx.compose.runtime.Composable public static androidx.glance.action.Action action(optional String? key, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+  public final class MutableActionParameters extends androidx.glance.action.ActionParameters {
+    method public java.util.Map<androidx.glance.action.ActionParameters.Key<?>,java.lang.Object> asMap();
+    method public void clear();
+    method public operator <T> boolean contains(androidx.glance.action.ActionParameters.Key<T> key);
+    method public operator <T> T? get(androidx.glance.action.ActionParameters.Key<T> key);
+    method public <T> T getOrDefault(androidx.glance.action.ActionParameters.Key<T> key, T defaultValue);
+    method public boolean isEmpty();
+    method public <T> T? remove(androidx.glance.action.ActionParameters.Key<T> key);
+    method public operator <T> T? set(androidx.glance.action.ActionParameters.Key<T> key, T? value);
+  }
+
+  public final class StartActivityActionKt {
+    method public static androidx.glance.action.Action actionStartActivity(android.content.ComponentName componentName, optional androidx.glance.action.ActionParameters parameters);
+    method public static <T extends android.app.Activity> androidx.glance.action.Action actionStartActivity(Class<T> activity, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action actionStartActivity(optional androidx.glance.action.ActionParameters parameters);
+  }
+
+}
+
+package androidx.glance.color {
+
+  public abstract sealed class ColorProviders {
+    method public final androidx.glance.unit.ColorProvider getBackground();
+    method public final androidx.glance.unit.ColorProvider getError();
+    method public final androidx.glance.unit.ColorProvider getErrorContainer();
+    method public final androidx.glance.unit.ColorProvider getInverseOnSurface();
+    method public final androidx.glance.unit.ColorProvider getInversePrimary();
+    method public final androidx.glance.unit.ColorProvider getInverseSurface();
+    method public final androidx.glance.unit.ColorProvider getOnBackground();
+    method public final androidx.glance.unit.ColorProvider getOnError();
+    method public final androidx.glance.unit.ColorProvider getOnErrorContainer();
+    method public final androidx.glance.unit.ColorProvider getOnPrimary();
+    method public final androidx.glance.unit.ColorProvider getOnPrimaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOnSecondary();
+    method public final androidx.glance.unit.ColorProvider getOnSecondaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOnSurface();
+    method public final androidx.glance.unit.ColorProvider getOnSurfaceVariant();
+    method public final androidx.glance.unit.ColorProvider getOnTertiary();
+    method public final androidx.glance.unit.ColorProvider getOnTertiaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOutline();
+    method public final androidx.glance.unit.ColorProvider getPrimary();
+    method public final androidx.glance.unit.ColorProvider getPrimaryContainer();
+    method public final androidx.glance.unit.ColorProvider getSecondary();
+    method public final androidx.glance.unit.ColorProvider getSecondaryContainer();
+    method public final androidx.glance.unit.ColorProvider getSurface();
+    method public final androidx.glance.unit.ColorProvider getSurfaceVariant();
+    method public final androidx.glance.unit.ColorProvider getTertiary();
+    method public final androidx.glance.unit.ColorProvider getTertiaryContainer();
+    property public final androidx.glance.unit.ColorProvider background;
+    property public final androidx.glance.unit.ColorProvider error;
+    property public final androidx.glance.unit.ColorProvider errorContainer;
+    property public final androidx.glance.unit.ColorProvider inverseOnSurface;
+    property public final androidx.glance.unit.ColorProvider inversePrimary;
+    property public final androidx.glance.unit.ColorProvider inverseSurface;
+    property public final androidx.glance.unit.ColorProvider onBackground;
+    property public final androidx.glance.unit.ColorProvider onError;
+    property public final androidx.glance.unit.ColorProvider onErrorContainer;
+    property public final androidx.glance.unit.ColorProvider onPrimary;
+    property public final androidx.glance.unit.ColorProvider onPrimaryContainer;
+    property public final androidx.glance.unit.ColorProvider onSecondary;
+    property public final androidx.glance.unit.ColorProvider onSecondaryContainer;
+    property public final androidx.glance.unit.ColorProvider onSurface;
+    property public final androidx.glance.unit.ColorProvider onSurfaceVariant;
+    property public final androidx.glance.unit.ColorProvider onTertiary;
+    property public final androidx.glance.unit.ColorProvider onTertiaryContainer;
+    property public final androidx.glance.unit.ColorProvider outline;
+    property public final androidx.glance.unit.ColorProvider primary;
+    property public final androidx.glance.unit.ColorProvider primaryContainer;
+    property public final androidx.glance.unit.ColorProvider secondary;
+    property public final androidx.glance.unit.ColorProvider secondaryContainer;
+    property public final androidx.glance.unit.ColorProvider surface;
+    property public final androidx.glance.unit.ColorProvider surfaceVariant;
+    property public final androidx.glance.unit.ColorProvider tertiary;
+    property public final androidx.glance.unit.ColorProvider tertiaryContainer;
+  }
+
+  public final class ColorProvidersKt {
+    method public static androidx.glance.color.ColorProviders colorProviders(androidx.glance.unit.ColorProvider primary, androidx.glance.unit.ColorProvider onPrimary, androidx.glance.unit.ColorProvider primaryContainer, androidx.glance.unit.ColorProvider onPrimaryContainer, androidx.glance.unit.ColorProvider secondary, androidx.glance.unit.ColorProvider onSecondary, androidx.glance.unit.ColorProvider secondaryContainer, androidx.glance.unit.ColorProvider onSecondaryContainer, androidx.glance.unit.ColorProvider tertiary, androidx.glance.unit.ColorProvider onTertiary, androidx.glance.unit.ColorProvider tertiaryContainer, androidx.glance.unit.ColorProvider onTertiaryContainer, androidx.glance.unit.ColorProvider error, androidx.glance.unit.ColorProvider errorContainer, androidx.glance.unit.ColorProvider onError, androidx.glance.unit.ColorProvider onErrorContainer, androidx.glance.unit.ColorProvider background, androidx.glance.unit.ColorProvider onBackground, androidx.glance.unit.ColorProvider surface, androidx.glance.unit.ColorProvider onSurface, androidx.glance.unit.ColorProvider surfaceVariant, androidx.glance.unit.ColorProvider onSurfaceVariant, androidx.glance.unit.ColorProvider outline, androidx.glance.unit.ColorProvider inverseOnSurface, androidx.glance.unit.ColorProvider inverseSurface, androidx.glance.unit.ColorProvider inversePrimary);
+  }
+
+  public final class DayNightColorProvidersKt {
+    method public static androidx.glance.unit.ColorProvider ColorProvider(long day, long night);
+  }
+
+}
+
+package androidx.glance.layout {
+
+  public final class Alignment {
+    ctor public Alignment(int horizontal, int vertical);
+    method public int getHorizontal();
+    method public int getVertical();
+    property public final int horizontal;
+    property public final int vertical;
+    field public static final androidx.glance.layout.Alignment.Companion Companion;
+  }
+
+  public static final class Alignment.Companion {
+    method public int getBottom();
+    method public androidx.glance.layout.Alignment getBottomCenter();
+    method public androidx.glance.layout.Alignment getBottomEnd();
+    method public androidx.glance.layout.Alignment getBottomStart();
+    method public androidx.glance.layout.Alignment getCenter();
+    method public androidx.glance.layout.Alignment getCenterEnd();
+    method public int getCenterHorizontally();
+    method public androidx.glance.layout.Alignment getCenterStart();
+    method public int getCenterVertically();
+    method public int getEnd();
+    method public int getStart();
+    method public int getTop();
+    method public androidx.glance.layout.Alignment getTopCenter();
+    method public androidx.glance.layout.Alignment getTopEnd();
+    method public androidx.glance.layout.Alignment getTopStart();
+    property public final int Bottom;
+    property public final androidx.glance.layout.Alignment BottomCenter;
+    property public final androidx.glance.layout.Alignment BottomEnd;
+    property public final androidx.glance.layout.Alignment BottomStart;
+    property public final androidx.glance.layout.Alignment Center;
+    property public final androidx.glance.layout.Alignment CenterEnd;
+    property public final int CenterHorizontally;
+    property public final androidx.glance.layout.Alignment CenterStart;
+    property public final int CenterVertically;
+    property public final int End;
+    property public final int Start;
+    property public final int Top;
+    property public final androidx.glance.layout.Alignment TopCenter;
+    property public final androidx.glance.layout.Alignment TopEnd;
+    property public final androidx.glance.layout.Alignment TopStart;
+  }
+
+  @kotlin.jvm.JvmInline public static final value class Alignment.Horizontal {
+    field public static final androidx.glance.layout.Alignment.Horizontal.Companion Companion;
+  }
+
+  public static final class Alignment.Horizontal.Companion {
+    method public int getCenterHorizontally();
+    method public int getEnd();
+    method public int getStart();
+    property public final int CenterHorizontally;
+    property public final int End;
+    property public final int Start;
+  }
+
+  @kotlin.jvm.JvmInline public static final value class Alignment.Vertical {
+    field public static final androidx.glance.layout.Alignment.Vertical.Companion Companion;
+  }
+
+  public static final class Alignment.Vertical.Companion {
+    method public int getBottom();
+    method public int getCenterVertically();
+    method public int getTop();
+    property public final int Bottom;
+    property public final int CenterVertically;
+    property public final int Top;
+  }
+
+  public final class BoxKt {
+    method @androidx.compose.runtime.Composable public static void Box(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.layout.Alignment contentAlignment, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ColumnKt {
+    method @androidx.compose.runtime.Composable public static void Column(optional androidx.glance.GlanceModifier modifier, optional int verticalAlignment, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  public interface ColumnScope {
+    method public androidx.glance.GlanceModifier defaultWeight(androidx.glance.GlanceModifier);
+  }
+
+  @kotlin.jvm.JvmInline public final value class ContentScale {
+    ctor public ContentScale(int value);
+    field public static final androidx.glance.layout.ContentScale.Companion Companion;
+  }
+
+  public static final class ContentScale.Companion {
+    method public int getCrop();
+    method public int getFillBounds();
+    method public int getFit();
+    property public final int Crop;
+    property public final int FillBounds;
+    property public final int Fit;
+  }
+
+  public final class PaddingKt {
+    method public static androidx.glance.GlanceModifier absolutePadding(androidx.glance.GlanceModifier, optional float left, optional float top, optional float right, optional float bottom);
+    method public static androidx.glance.GlanceModifier absolutePadding(androidx.glance.GlanceModifier, optional @DimenRes int left, optional @DimenRes int top, optional @DimenRes int right, optional @DimenRes int bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional float start, optional float top, optional float end, optional float bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional @DimenRes int start, optional @DimenRes int top, optional @DimenRes int end, optional @DimenRes int bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional float horizontal, optional float vertical);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional @DimenRes int horizontal, optional @DimenRes int vertical);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, float all);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, @DimenRes int all);
+  }
+
+  public final class RowKt {
+    method @androidx.compose.runtime.Composable public static void Row(optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, optional int verticalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.layout.RowScope,kotlin.Unit> content);
+  }
+
+  public interface RowScope {
+    method public androidx.glance.GlanceModifier defaultWeight(androidx.glance.GlanceModifier);
+  }
+
+  public final class SizeModifiersKt {
+    method public static androidx.glance.GlanceModifier fillMaxHeight(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier fillMaxSize(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier fillMaxWidth(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier height(androidx.glance.GlanceModifier, float height);
+    method public static androidx.glance.GlanceModifier height(androidx.glance.GlanceModifier, @DimenRes int height);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, float size);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, @DimenRes int size);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, float width, float height);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, @DimenRes int width, @DimenRes int height);
+    method public static androidx.glance.GlanceModifier width(androidx.glance.GlanceModifier, float width);
+    method public static androidx.glance.GlanceModifier width(androidx.glance.GlanceModifier, @DimenRes int width);
+    method public static androidx.glance.GlanceModifier wrapContentHeight(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier wrapContentSize(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier wrapContentWidth(androidx.glance.GlanceModifier);
+  }
+
+  public final class SpacerKt {
+    method @androidx.compose.runtime.Composable public static void Spacer(optional androidx.glance.GlanceModifier modifier);
+  }
+
+}
+
+package androidx.glance.semantics {
+
+  public final class SemanticsConfiguration implements androidx.glance.semantics.SemanticsPropertyReceiver {
+    ctor public SemanticsConfiguration();
+    method public operator <T> T get(androidx.glance.semantics.SemanticsPropertyKey<T> key);
+    method public <T> T? getOrElseNullable(androidx.glance.semantics.SemanticsPropertyKey<T> key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+    method public <T> T? getOrNull(androidx.glance.semantics.SemanticsPropertyKey<T> key);
+    method public <T> void set(androidx.glance.semantics.SemanticsPropertyKey<T> key, T value);
+  }
+
+  public final class SemanticsModifierKt {
+    method public static androidx.glance.GlanceModifier semantics(androidx.glance.GlanceModifier, kotlin.jvm.functions.Function1<? super androidx.glance.semantics.SemanticsPropertyReceiver,kotlin.Unit> properties);
+  }
+
+  public final class SemanticsProperties {
+    method public androidx.glance.semantics.SemanticsPropertyKey<java.util.List<java.lang.String>> getContentDescription();
+    property public final androidx.glance.semantics.SemanticsPropertyKey<java.util.List<java.lang.String>> ContentDescription;
+    field public static final androidx.glance.semantics.SemanticsProperties INSTANCE;
+  }
+
+  public final class SemanticsPropertiesKt {
+    method public static String getContentDescription(androidx.glance.semantics.SemanticsPropertyReceiver);
+    method public static void setContentDescription(androidx.glance.semantics.SemanticsPropertyReceiver, String);
+  }
+
+  public final class SemanticsPropertyKey<T> {
+    ctor public SemanticsPropertyKey(String name, optional kotlin.jvm.functions.Function2<? super T,? super T,? extends T> mergePolicy);
+    method public String getName();
+    method public T? merge(T? parentValue, T childValue);
+    property public final String name;
+  }
+
+  public interface SemanticsPropertyReceiver {
+    method public operator <T> void set(androidx.glance.semantics.SemanticsPropertyKey<T> key, T value);
+  }
+
+}
+
+package androidx.glance.session {
+
+  public final class SessionManagerKt {
+  }
+
+}
+
+package androidx.glance.state {
+
+  public interface GlanceStateDefinition<T> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>>);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
+  }
+
+  public final class PreferencesGlanceStateDefinition implements androidx.glance.state.GlanceStateDefinition<androidx.datastore.preferences.core.Preferences> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<androidx.datastore.preferences.core.Preferences>>);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
+    field public static final androidx.glance.state.PreferencesGlanceStateDefinition INSTANCE;
+  }
+
+}
+
+package androidx.glance.text {
+
+  public final class FontFamily {
+    ctor public FontFamily(String family);
+    method public String getFamily();
+    property public final String family;
+    field public static final androidx.glance.text.FontFamily.Companion Companion;
+  }
+
+  public static final class FontFamily.Companion {
+    method public androidx.glance.text.FontFamily getCursive();
+    method public androidx.glance.text.FontFamily getMonospace();
+    method public androidx.glance.text.FontFamily getSansSerif();
+    method public androidx.glance.text.FontFamily getSerif();
+    property public final androidx.glance.text.FontFamily Cursive;
+    property public final androidx.glance.text.FontFamily Monospace;
+    property public final androidx.glance.text.FontFamily SansSerif;
+    property public final androidx.glance.text.FontFamily Serif;
+  }
+
+  @kotlin.jvm.JvmInline public final value class FontStyle {
+    field public static final androidx.glance.text.FontStyle.Companion Companion;
+  }
+
+  public static final class FontStyle.Companion {
+    method public int getItalic();
+    method public int getNormal();
+    method public java.util.List<androidx.glance.text.FontStyle> values();
+    property public final int Italic;
+    property public final int Normal;
+  }
+
+  @kotlin.jvm.JvmInline public final value class FontWeight {
+    method public int getValue();
+    property public final int value;
+    field public static final androidx.glance.text.FontWeight.Companion Companion;
+  }
+
+  public static final class FontWeight.Companion {
+    method public int getBold();
+    method public int getMedium();
+    method public int getNormal();
+    property public final int Bold;
+    property public final int Medium;
+    property public final int Normal;
+  }
+
+  @kotlin.jvm.JvmInline public final value class TextAlign {
+    field public static final androidx.glance.text.TextAlign.Companion Companion;
+  }
+
+  public static final class TextAlign.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    method public int getLeft();
+    method public int getRight();
+    method public int getStart();
+    method public java.util.List<androidx.glance.text.TextAlign> values();
+    property public final int Center;
+    property public final int End;
+    property public final int Left;
+    property public final int Right;
+    property public final int Start;
+  }
+
+  @kotlin.jvm.JvmInline public final value class TextDecoration {
+    method @androidx.compose.runtime.Stable public operator boolean contains(int other);
+    method @androidx.compose.runtime.Stable public operator int plus(int decoration);
+    field public static final androidx.glance.text.TextDecoration.Companion Companion;
+  }
+
+  public static final class TextDecoration.Companion {
+    method public int combine(java.util.List<androidx.glance.text.TextDecoration> decorations);
+    method public int getLineThrough();
+    method public int getNone();
+    method public int getUnderline();
+    property public final int LineThrough;
+    property public final int None;
+    property public final int Underline;
+  }
+
+  public final class TextDefaults {
+    method public androidx.glance.unit.ColorProvider getDefaultTextColor();
+    method public androidx.glance.text.TextStyle getDefaultTextStyle();
+    property public final androidx.glance.unit.ColorProvider defaultTextColor;
+    property public final androidx.glance.text.TextStyle defaultTextStyle;
+    field public static final androidx.glance.text.TextDefaults INSTANCE;
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.glance.GlanceModifier modifier, optional androidx.glance.text.TextStyle style, optional int maxLines);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextStyle {
+    ctor public TextStyle(optional androidx.glance.unit.ColorProvider color, optional androidx.compose.ui.unit.TextUnit? fontSize, optional androidx.glance.text.FontWeight? fontWeight, optional androidx.glance.text.FontStyle? fontStyle, optional androidx.glance.text.TextAlign? textAlign, optional androidx.glance.text.TextDecoration? textDecoration, optional androidx.glance.text.FontFamily? fontFamily);
+    method public androidx.glance.text.TextStyle copy(optional androidx.glance.unit.ColorProvider color, optional androidx.compose.ui.unit.TextUnit? fontSize, optional androidx.glance.text.FontWeight? fontWeight, optional androidx.glance.text.FontStyle? fontStyle, optional androidx.glance.text.TextAlign? textAlign, optional androidx.glance.text.TextDecoration? textDecoration, optional androidx.glance.text.FontFamily? fontFamily);
+    method public androidx.glance.unit.ColorProvider getColor();
+    method public androidx.glance.text.FontFamily? getFontFamily();
+    method public androidx.compose.ui.unit.TextUnit? getFontSize();
+    method public androidx.glance.text.FontStyle? getFontStyle();
+    method public androidx.glance.text.FontWeight? getFontWeight();
+    method public androidx.glance.text.TextAlign? getTextAlign();
+    method public androidx.glance.text.TextDecoration? getTextDecoration();
+    property public final androidx.glance.unit.ColorProvider color;
+    property public final androidx.glance.text.FontFamily? fontFamily;
+    property public final androidx.compose.ui.unit.TextUnit? fontSize;
+    property public final androidx.glance.text.FontStyle? fontStyle;
+    property public final androidx.glance.text.FontWeight? fontWeight;
+    property public final androidx.glance.text.TextAlign? textAlign;
+    property public final androidx.glance.text.TextDecoration? textDecoration;
+  }
+
+}
+
+package androidx.glance.unit {
+
+  public interface ColorProvider {
+    method public long getColor(android.content.Context context);
+  }
+
+  public final class ColorProviderKt {
+    method public static androidx.glance.unit.ColorProvider ColorProvider(long color);
+  }
+
+}
+
diff --git a/glance/glance/api/res-1.0.0-beta01.txt b/glance/glance/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/glance/glance/api/res-1.0.0-beta01.txt
diff --git a/glance/glance/api/restricted_1.0.0-beta01.txt b/glance/glance/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..47d790f
--- /dev/null
+++ b/glance/glance/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,569 @@
+// Signature format: 4.0
+package androidx.glance {
+
+  public final class BackgroundKt {
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, long color);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, @ColorRes int color);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, androidx.glance.unit.ColorProvider colorProvider);
+    method public static androidx.glance.GlanceModifier background(androidx.glance.GlanceModifier, androidx.glance.ImageProvider imageProvider, optional int contentScale);
+  }
+
+  public final class ButtonColors {
+    method public androidx.glance.unit.ColorProvider getBackgroundColor();
+    method public androidx.glance.unit.ColorProvider getContentColor();
+    property public final androidx.glance.unit.ColorProvider backgroundColor;
+    property public final androidx.glance.unit.ColorProvider contentColor;
+  }
+
+  public final class ButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.glance.ButtonColors buttonColors(optional androidx.glance.unit.ColorProvider backgroundColor, optional androidx.glance.unit.ColorProvider contentColor);
+    field public static final androidx.glance.ButtonDefaults INSTANCE;
+  }
+
+  public final class ButtonKt {
+    method @androidx.compose.runtime.Composable public static void Button(String text, androidx.glance.action.Action onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional androidx.glance.text.TextStyle? style, optional androidx.glance.ButtonColors colors, optional int maxLines);
+    method @androidx.compose.runtime.Composable public static void Button(String text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.glance.GlanceModifier modifier, optional boolean enabled, optional androidx.glance.text.TextStyle? style, optional androidx.glance.ButtonColors colors, optional int maxLines);
+  }
+
+  public final class ColorFilter {
+    field public static final androidx.glance.ColorFilter.Companion Companion;
+  }
+
+  public static final class ColorFilter.Companion {
+    method public androidx.glance.ColorFilter tint(androidx.glance.unit.ColorProvider colorProvider);
+  }
+
+  public final class CombinedGlanceModifier implements androidx.glance.GlanceModifier {
+    ctor public CombinedGlanceModifier(androidx.glance.GlanceModifier outer, androidx.glance.GlanceModifier inner);
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  public final class CompositionLocalsKt {
+    method @androidx.compose.runtime.Composable public static inline <reified T> T currentState();
+    method @androidx.compose.runtime.Composable public static inline <reified T> T? currentState(androidx.datastore.preferences.core.Preferences.Key<T> key);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<android.content.Context> getLocalContext();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.GlanceId> getLocalGlanceId();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.DpSize> getLocalSize();
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Object> getLocalState();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.content.Context> LocalContext;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.GlanceId> LocalGlanceId;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.DpSize> LocalSize;
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Object> LocalState;
+  }
+
+  @androidx.compose.runtime.ComposableTargetMarker(description="Glance Composable") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.FILE, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.TYPE, kotlin.annotation.AnnotationTarget.TYPE_PARAMETER}) public @interface GlanceComposable {
+  }
+
+  public interface GlanceId {
+  }
+
+  @androidx.compose.runtime.Stable @kotlin.jvm.JvmDefaultWithCompatibility public interface GlanceModifier {
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+    method public default infix androidx.glance.GlanceModifier then(androidx.glance.GlanceModifier other);
+    field public static final androidx.glance.GlanceModifier.Companion Companion;
+  }
+
+  public static final class GlanceModifier.Companion implements androidx.glance.GlanceModifier {
+    method public boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public static interface GlanceModifier.Element extends androidx.glance.GlanceModifier {
+    method public default boolean all(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public default boolean any(kotlin.jvm.functions.Function1<? super androidx.glance.GlanceModifier.Element,java.lang.Boolean> predicate);
+    method public default <R> R foldIn(R initial, kotlin.jvm.functions.Function2<? super R,? super androidx.glance.GlanceModifier.Element,? extends R> operation);
+    method public default <R> R foldOut(R initial, kotlin.jvm.functions.Function2<? super androidx.glance.GlanceModifier.Element,? super R,? extends R> operation);
+  }
+
+  public final class GlanceTheme {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable @androidx.glance.GlanceComposable public androidx.glance.color.ColorProviders getColors();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable @androidx.glance.GlanceComposable public final androidx.glance.color.ColorProviders colors;
+    field public static final androidx.glance.GlanceTheme INSTANCE;
+  }
+
+  public final class GlanceThemeKt {
+    method @androidx.compose.runtime.Composable public static void GlanceTheme(optional androidx.glance.color.ColorProviders colors, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ImageKt {
+    method @androidx.compose.runtime.Composable public static void Image(androidx.glance.ImageProvider provider, String? contentDescription, optional androidx.glance.GlanceModifier modifier, optional int contentScale, optional androidx.glance.ColorFilter? colorFilter);
+    method public static androidx.glance.ImageProvider ImageProvider(@DrawableRes int resId);
+    method public static androidx.glance.ImageProvider ImageProvider(android.graphics.Bitmap bitmap);
+    method @RequiresApi(android.os.Build.VERSION_CODES.M) public static androidx.glance.ImageProvider ImageProvider(android.graphics.drawable.Icon icon);
+  }
+
+  public interface ImageProvider {
+  }
+
+  public enum Visibility {
+    method public static androidx.glance.Visibility valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.glance.Visibility[] values();
+    enum_constant public static final androidx.glance.Visibility Gone;
+    enum_constant public static final androidx.glance.Visibility Invisible;
+    enum_constant public static final androidx.glance.Visibility Visible;
+  }
+
+  public final class VisibilityKt {
+    method public static androidx.glance.GlanceModifier visibility(androidx.glance.GlanceModifier, androidx.glance.Visibility visibility);
+  }
+
+}
+
+package androidx.glance.action {
+
+  public interface Action {
+  }
+
+  public final class ActionKt {
+    method public static androidx.glance.GlanceModifier clickable(androidx.glance.GlanceModifier, androidx.glance.action.Action onClick);
+    method @androidx.compose.runtime.Composable public static androidx.glance.GlanceModifier clickable(androidx.glance.GlanceModifier, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+  public abstract class ActionParameters {
+    method public abstract java.util.Map<androidx.glance.action.ActionParameters.Key<?>,java.lang.Object> asMap();
+    method public abstract operator <T> boolean contains(androidx.glance.action.ActionParameters.Key<T> key);
+    method public abstract operator <T> T? get(androidx.glance.action.ActionParameters.Key<T> key);
+    method public abstract <T> T getOrDefault(androidx.glance.action.ActionParameters.Key<T> key, T defaultValue);
+    method public abstract boolean isEmpty();
+  }
+
+  public static final class ActionParameters.Key<T> {
+    ctor public ActionParameters.Key(String name);
+    method public String getName();
+    method public infix androidx.glance.action.ActionParameters.Pair<T> to(T value);
+    property public final String name;
+  }
+
+  public static final class ActionParameters.Pair<T> {
+  }
+
+  public final class ActionParametersKt {
+    method public static androidx.glance.action.ActionParameters actionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
+    method public static androidx.glance.action.MutableActionParameters mutableActionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
+    method public static androidx.glance.action.MutableActionParameters toMutableParameters(androidx.glance.action.ActionParameters);
+    method public static androidx.glance.action.ActionParameters toParameters(androidx.glance.action.ActionParameters);
+    method public static <T> androidx.glance.action.ActionParameters.Key<T> toParametersKey(androidx.datastore.preferences.core.Preferences.Key<T>);
+  }
+
+  public final class LambdaActionKt {
+    method @androidx.compose.runtime.Composable public static androidx.glance.action.Action action(optional String? key, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+  public final class MutableActionParameters extends androidx.glance.action.ActionParameters {
+    method public java.util.Map<androidx.glance.action.ActionParameters.Key<?>,java.lang.Object> asMap();
+    method public void clear();
+    method public operator <T> boolean contains(androidx.glance.action.ActionParameters.Key<T> key);
+    method public operator <T> T? get(androidx.glance.action.ActionParameters.Key<T> key);
+    method public <T> T getOrDefault(androidx.glance.action.ActionParameters.Key<T> key, T defaultValue);
+    method public boolean isEmpty();
+    method public <T> T? remove(androidx.glance.action.ActionParameters.Key<T> key);
+    method public operator <T> T? set(androidx.glance.action.ActionParameters.Key<T> key, T? value);
+  }
+
+  public final class StartActivityActionKt {
+    method public static androidx.glance.action.Action actionStartActivity(android.content.ComponentName componentName, optional androidx.glance.action.ActionParameters parameters);
+    method public static <T extends android.app.Activity> androidx.glance.action.Action actionStartActivity(Class<T> activity, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action actionStartActivity(optional androidx.glance.action.ActionParameters parameters);
+  }
+
+}
+
+package androidx.glance.color {
+
+  public abstract sealed class ColorProviders {
+    method public final androidx.glance.unit.ColorProvider getBackground();
+    method public final androidx.glance.unit.ColorProvider getError();
+    method public final androidx.glance.unit.ColorProvider getErrorContainer();
+    method public final androidx.glance.unit.ColorProvider getInverseOnSurface();
+    method public final androidx.glance.unit.ColorProvider getInversePrimary();
+    method public final androidx.glance.unit.ColorProvider getInverseSurface();
+    method public final androidx.glance.unit.ColorProvider getOnBackground();
+    method public final androidx.glance.unit.ColorProvider getOnError();
+    method public final androidx.glance.unit.ColorProvider getOnErrorContainer();
+    method public final androidx.glance.unit.ColorProvider getOnPrimary();
+    method public final androidx.glance.unit.ColorProvider getOnPrimaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOnSecondary();
+    method public final androidx.glance.unit.ColorProvider getOnSecondaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOnSurface();
+    method public final androidx.glance.unit.ColorProvider getOnSurfaceVariant();
+    method public final androidx.glance.unit.ColorProvider getOnTertiary();
+    method public final androidx.glance.unit.ColorProvider getOnTertiaryContainer();
+    method public final androidx.glance.unit.ColorProvider getOutline();
+    method public final androidx.glance.unit.ColorProvider getPrimary();
+    method public final androidx.glance.unit.ColorProvider getPrimaryContainer();
+    method public final androidx.glance.unit.ColorProvider getSecondary();
+    method public final androidx.glance.unit.ColorProvider getSecondaryContainer();
+    method public final androidx.glance.unit.ColorProvider getSurface();
+    method public final androidx.glance.unit.ColorProvider getSurfaceVariant();
+    method public final androidx.glance.unit.ColorProvider getTertiary();
+    method public final androidx.glance.unit.ColorProvider getTertiaryContainer();
+    property public final androidx.glance.unit.ColorProvider background;
+    property public final androidx.glance.unit.ColorProvider error;
+    property public final androidx.glance.unit.ColorProvider errorContainer;
+    property public final androidx.glance.unit.ColorProvider inverseOnSurface;
+    property public final androidx.glance.unit.ColorProvider inversePrimary;
+    property public final androidx.glance.unit.ColorProvider inverseSurface;
+    property public final androidx.glance.unit.ColorProvider onBackground;
+    property public final androidx.glance.unit.ColorProvider onError;
+    property public final androidx.glance.unit.ColorProvider onErrorContainer;
+    property public final androidx.glance.unit.ColorProvider onPrimary;
+    property public final androidx.glance.unit.ColorProvider onPrimaryContainer;
+    property public final androidx.glance.unit.ColorProvider onSecondary;
+    property public final androidx.glance.unit.ColorProvider onSecondaryContainer;
+    property public final androidx.glance.unit.ColorProvider onSurface;
+    property public final androidx.glance.unit.ColorProvider onSurfaceVariant;
+    property public final androidx.glance.unit.ColorProvider onTertiary;
+    property public final androidx.glance.unit.ColorProvider onTertiaryContainer;
+    property public final androidx.glance.unit.ColorProvider outline;
+    property public final androidx.glance.unit.ColorProvider primary;
+    property public final androidx.glance.unit.ColorProvider primaryContainer;
+    property public final androidx.glance.unit.ColorProvider secondary;
+    property public final androidx.glance.unit.ColorProvider secondaryContainer;
+    property public final androidx.glance.unit.ColorProvider surface;
+    property public final androidx.glance.unit.ColorProvider surfaceVariant;
+    property public final androidx.glance.unit.ColorProvider tertiary;
+    property public final androidx.glance.unit.ColorProvider tertiaryContainer;
+  }
+
+  public final class ColorProvidersKt {
+    method public static androidx.glance.color.ColorProviders colorProviders(androidx.glance.unit.ColorProvider primary, androidx.glance.unit.ColorProvider onPrimary, androidx.glance.unit.ColorProvider primaryContainer, androidx.glance.unit.ColorProvider onPrimaryContainer, androidx.glance.unit.ColorProvider secondary, androidx.glance.unit.ColorProvider onSecondary, androidx.glance.unit.ColorProvider secondaryContainer, androidx.glance.unit.ColorProvider onSecondaryContainer, androidx.glance.unit.ColorProvider tertiary, androidx.glance.unit.ColorProvider onTertiary, androidx.glance.unit.ColorProvider tertiaryContainer, androidx.glance.unit.ColorProvider onTertiaryContainer, androidx.glance.unit.ColorProvider error, androidx.glance.unit.ColorProvider errorContainer, androidx.glance.unit.ColorProvider onError, androidx.glance.unit.ColorProvider onErrorContainer, androidx.glance.unit.ColorProvider background, androidx.glance.unit.ColorProvider onBackground, androidx.glance.unit.ColorProvider surface, androidx.glance.unit.ColorProvider onSurface, androidx.glance.unit.ColorProvider surfaceVariant, androidx.glance.unit.ColorProvider onSurfaceVariant, androidx.glance.unit.ColorProvider outline, androidx.glance.unit.ColorProvider inverseOnSurface, androidx.glance.unit.ColorProvider inverseSurface, androidx.glance.unit.ColorProvider inversePrimary);
+  }
+
+  public final class DayNightColorProvidersKt {
+    method public static androidx.glance.unit.ColorProvider ColorProvider(long day, long night);
+  }
+
+}
+
+package androidx.glance.layout {
+
+  public final class Alignment {
+    ctor public Alignment(int horizontal, int vertical);
+    method public int getHorizontal();
+    method public int getVertical();
+    property public final int horizontal;
+    property public final int vertical;
+    field public static final androidx.glance.layout.Alignment.Companion Companion;
+  }
+
+  public static final class Alignment.Companion {
+    method public int getBottom();
+    method public androidx.glance.layout.Alignment getBottomCenter();
+    method public androidx.glance.layout.Alignment getBottomEnd();
+    method public androidx.glance.layout.Alignment getBottomStart();
+    method public androidx.glance.layout.Alignment getCenter();
+    method public androidx.glance.layout.Alignment getCenterEnd();
+    method public int getCenterHorizontally();
+    method public androidx.glance.layout.Alignment getCenterStart();
+    method public int getCenterVertically();
+    method public int getEnd();
+    method public int getStart();
+    method public int getTop();
+    method public androidx.glance.layout.Alignment getTopCenter();
+    method public androidx.glance.layout.Alignment getTopEnd();
+    method public androidx.glance.layout.Alignment getTopStart();
+    property public final int Bottom;
+    property public final androidx.glance.layout.Alignment BottomCenter;
+    property public final androidx.glance.layout.Alignment BottomEnd;
+    property public final androidx.glance.layout.Alignment BottomStart;
+    property public final androidx.glance.layout.Alignment Center;
+    property public final androidx.glance.layout.Alignment CenterEnd;
+    property public final int CenterHorizontally;
+    property public final androidx.glance.layout.Alignment CenterStart;
+    property public final int CenterVertically;
+    property public final int End;
+    property public final int Start;
+    property public final int Top;
+    property public final androidx.glance.layout.Alignment TopCenter;
+    property public final androidx.glance.layout.Alignment TopEnd;
+    property public final androidx.glance.layout.Alignment TopStart;
+  }
+
+  @kotlin.jvm.JvmInline public static final value class Alignment.Horizontal {
+    field public static final androidx.glance.layout.Alignment.Horizontal.Companion Companion;
+  }
+
+  public static final class Alignment.Horizontal.Companion {
+    method public int getCenterHorizontally();
+    method public int getEnd();
+    method public int getStart();
+    property public final int CenterHorizontally;
+    property public final int End;
+    property public final int Start;
+  }
+
+  @kotlin.jvm.JvmInline public static final value class Alignment.Vertical {
+    field public static final androidx.glance.layout.Alignment.Vertical.Companion Companion;
+  }
+
+  public static final class Alignment.Vertical.Companion {
+    method public int getBottom();
+    method public int getCenterVertically();
+    method public int getTop();
+    property public final int Bottom;
+    property public final int CenterVertically;
+    property public final int Top;
+  }
+
+  public final class BoxKt {
+    method @androidx.compose.runtime.Composable public static void Box(optional androidx.glance.GlanceModifier modifier, optional androidx.glance.layout.Alignment contentAlignment, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ColumnKt {
+    method @androidx.compose.runtime.Composable public static void Column(optional androidx.glance.GlanceModifier modifier, optional int verticalAlignment, optional int horizontalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  public interface ColumnScope {
+    method public androidx.glance.GlanceModifier defaultWeight(androidx.glance.GlanceModifier);
+  }
+
+  @kotlin.jvm.JvmInline public final value class ContentScale {
+    ctor public ContentScale(int value);
+    field public static final androidx.glance.layout.ContentScale.Companion Companion;
+  }
+
+  public static final class ContentScale.Companion {
+    method public int getCrop();
+    method public int getFillBounds();
+    method public int getFit();
+    property public final int Crop;
+    property public final int FillBounds;
+    property public final int Fit;
+  }
+
+  public final class PaddingKt {
+    method public static androidx.glance.GlanceModifier absolutePadding(androidx.glance.GlanceModifier, optional float left, optional float top, optional float right, optional float bottom);
+    method public static androidx.glance.GlanceModifier absolutePadding(androidx.glance.GlanceModifier, optional @DimenRes int left, optional @DimenRes int top, optional @DimenRes int right, optional @DimenRes int bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional float start, optional float top, optional float end, optional float bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional @DimenRes int start, optional @DimenRes int top, optional @DimenRes int end, optional @DimenRes int bottom);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional float horizontal, optional float vertical);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, optional @DimenRes int horizontal, optional @DimenRes int vertical);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, float all);
+    method public static androidx.glance.GlanceModifier padding(androidx.glance.GlanceModifier, @DimenRes int all);
+  }
+
+  public final class RowKt {
+    method @androidx.compose.runtime.Composable public static void Row(optional androidx.glance.GlanceModifier modifier, optional int horizontalAlignment, optional int verticalAlignment, kotlin.jvm.functions.Function1<? super androidx.glance.layout.RowScope,kotlin.Unit> content);
+  }
+
+  public interface RowScope {
+    method public androidx.glance.GlanceModifier defaultWeight(androidx.glance.GlanceModifier);
+  }
+
+  public final class SizeModifiersKt {
+    method public static androidx.glance.GlanceModifier fillMaxHeight(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier fillMaxSize(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier fillMaxWidth(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier height(androidx.glance.GlanceModifier, float height);
+    method public static androidx.glance.GlanceModifier height(androidx.glance.GlanceModifier, @DimenRes int height);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, float size);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, @DimenRes int size);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, float width, float height);
+    method public static androidx.glance.GlanceModifier size(androidx.glance.GlanceModifier, @DimenRes int width, @DimenRes int height);
+    method public static androidx.glance.GlanceModifier width(androidx.glance.GlanceModifier, float width);
+    method public static androidx.glance.GlanceModifier width(androidx.glance.GlanceModifier, @DimenRes int width);
+    method public static androidx.glance.GlanceModifier wrapContentHeight(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier wrapContentSize(androidx.glance.GlanceModifier);
+    method public static androidx.glance.GlanceModifier wrapContentWidth(androidx.glance.GlanceModifier);
+  }
+
+  public final class SpacerKt {
+    method @androidx.compose.runtime.Composable public static void Spacer(optional androidx.glance.GlanceModifier modifier);
+  }
+
+}
+
+package androidx.glance.semantics {
+
+  public final class SemanticsConfiguration implements androidx.glance.semantics.SemanticsPropertyReceiver {
+    ctor public SemanticsConfiguration();
+    method public operator <T> T get(androidx.glance.semantics.SemanticsPropertyKey<T> key);
+    method public <T> T? getOrElseNullable(androidx.glance.semantics.SemanticsPropertyKey<T> key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+    method public <T> T? getOrNull(androidx.glance.semantics.SemanticsPropertyKey<T> key);
+    method public <T> void set(androidx.glance.semantics.SemanticsPropertyKey<T> key, T value);
+  }
+
+  public final class SemanticsModifierKt {
+    method public static androidx.glance.GlanceModifier semantics(androidx.glance.GlanceModifier, kotlin.jvm.functions.Function1<? super androidx.glance.semantics.SemanticsPropertyReceiver,kotlin.Unit> properties);
+  }
+
+  public final class SemanticsProperties {
+    method public androidx.glance.semantics.SemanticsPropertyKey<java.util.List<java.lang.String>> getContentDescription();
+    property public final androidx.glance.semantics.SemanticsPropertyKey<java.util.List<java.lang.String>> ContentDescription;
+    field public static final androidx.glance.semantics.SemanticsProperties INSTANCE;
+  }
+
+  public final class SemanticsPropertiesKt {
+    method public static String getContentDescription(androidx.glance.semantics.SemanticsPropertyReceiver);
+    method public static void setContentDescription(androidx.glance.semantics.SemanticsPropertyReceiver, String);
+  }
+
+  public final class SemanticsPropertyKey<T> {
+    ctor public SemanticsPropertyKey(String name, optional kotlin.jvm.functions.Function2<? super T,? super T,? extends T> mergePolicy);
+    method public String getName();
+    method public T? merge(T? parentValue, T childValue);
+    property public final String name;
+  }
+
+  public interface SemanticsPropertyReceiver {
+    method public operator <T> void set(androidx.glance.semantics.SemanticsPropertyKey<T> key, T value);
+  }
+
+}
+
+package androidx.glance.session {
+
+  public final class SessionManagerKt {
+  }
+
+}
+
+package androidx.glance.state {
+
+  public interface GlanceStateDefinition<T> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>>);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
+  }
+
+  public final class PreferencesGlanceStateDefinition implements androidx.glance.state.GlanceStateDefinition<androidx.datastore.preferences.core.Preferences> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<androidx.datastore.preferences.core.Preferences>>);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
+    field public static final androidx.glance.state.PreferencesGlanceStateDefinition INSTANCE;
+  }
+
+}
+
+package androidx.glance.text {
+
+  public final class FontFamily {
+    ctor public FontFamily(String family);
+    method public String getFamily();
+    property public final String family;
+    field public static final androidx.glance.text.FontFamily.Companion Companion;
+  }
+
+  public static final class FontFamily.Companion {
+    method public androidx.glance.text.FontFamily getCursive();
+    method public androidx.glance.text.FontFamily getMonospace();
+    method public androidx.glance.text.FontFamily getSansSerif();
+    method public androidx.glance.text.FontFamily getSerif();
+    property public final androidx.glance.text.FontFamily Cursive;
+    property public final androidx.glance.text.FontFamily Monospace;
+    property public final androidx.glance.text.FontFamily SansSerif;
+    property public final androidx.glance.text.FontFamily Serif;
+  }
+
+  @kotlin.jvm.JvmInline public final value class FontStyle {
+    field public static final androidx.glance.text.FontStyle.Companion Companion;
+  }
+
+  public static final class FontStyle.Companion {
+    method public int getItalic();
+    method public int getNormal();
+    method public java.util.List<androidx.glance.text.FontStyle> values();
+    property public final int Italic;
+    property public final int Normal;
+  }
+
+  @kotlin.jvm.JvmInline public final value class FontWeight {
+    method public int getValue();
+    property public final int value;
+    field public static final androidx.glance.text.FontWeight.Companion Companion;
+  }
+
+  public static final class FontWeight.Companion {
+    method public int getBold();
+    method public int getMedium();
+    method public int getNormal();
+    property public final int Bold;
+    property public final int Medium;
+    property public final int Normal;
+  }
+
+  @kotlin.jvm.JvmInline public final value class TextAlign {
+    field public static final androidx.glance.text.TextAlign.Companion Companion;
+  }
+
+  public static final class TextAlign.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    method public int getLeft();
+    method public int getRight();
+    method public int getStart();
+    method public java.util.List<androidx.glance.text.TextAlign> values();
+    property public final int Center;
+    property public final int End;
+    property public final int Left;
+    property public final int Right;
+    property public final int Start;
+  }
+
+  @kotlin.jvm.JvmInline public final value class TextDecoration {
+    method @androidx.compose.runtime.Stable public operator boolean contains(int other);
+    method @androidx.compose.runtime.Stable public operator int plus(int decoration);
+    field public static final androidx.glance.text.TextDecoration.Companion Companion;
+  }
+
+  public static final class TextDecoration.Companion {
+    method public int combine(java.util.List<androidx.glance.text.TextDecoration> decorations);
+    method public int getLineThrough();
+    method public int getNone();
+    method public int getUnderline();
+    property public final int LineThrough;
+    property public final int None;
+    property public final int Underline;
+  }
+
+  public final class TextDefaults {
+    method public androidx.glance.unit.ColorProvider getDefaultTextColor();
+    method public androidx.glance.text.TextStyle getDefaultTextStyle();
+    property public final androidx.glance.unit.ColorProvider defaultTextColor;
+    property public final androidx.glance.text.TextStyle defaultTextStyle;
+    field public static final androidx.glance.text.TextDefaults INSTANCE;
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.glance.GlanceModifier modifier, optional androidx.glance.text.TextStyle style, optional int maxLines);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextStyle {
+    ctor public TextStyle(optional androidx.glance.unit.ColorProvider color, optional androidx.compose.ui.unit.TextUnit? fontSize, optional androidx.glance.text.FontWeight? fontWeight, optional androidx.glance.text.FontStyle? fontStyle, optional androidx.glance.text.TextAlign? textAlign, optional androidx.glance.text.TextDecoration? textDecoration, optional androidx.glance.text.FontFamily? fontFamily);
+    method public androidx.glance.text.TextStyle copy(optional androidx.glance.unit.ColorProvider color, optional androidx.compose.ui.unit.TextUnit? fontSize, optional androidx.glance.text.FontWeight? fontWeight, optional androidx.glance.text.FontStyle? fontStyle, optional androidx.glance.text.TextAlign? textAlign, optional androidx.glance.text.TextDecoration? textDecoration, optional androidx.glance.text.FontFamily? fontFamily);
+    method public androidx.glance.unit.ColorProvider getColor();
+    method public androidx.glance.text.FontFamily? getFontFamily();
+    method public androidx.compose.ui.unit.TextUnit? getFontSize();
+    method public androidx.glance.text.FontStyle? getFontStyle();
+    method public androidx.glance.text.FontWeight? getFontWeight();
+    method public androidx.glance.text.TextAlign? getTextAlign();
+    method public androidx.glance.text.TextDecoration? getTextDecoration();
+    property public final androidx.glance.unit.ColorProvider color;
+    property public final androidx.glance.text.FontFamily? fontFamily;
+    property public final androidx.compose.ui.unit.TextUnit? fontSize;
+    property public final androidx.glance.text.FontStyle? fontStyle;
+    property public final androidx.glance.text.FontWeight? fontWeight;
+    property public final androidx.glance.text.TextAlign? textAlign;
+    property public final androidx.glance.text.TextDecoration? textDecoration;
+  }
+
+}
+
+package androidx.glance.unit {
+
+  public interface ColorProvider {
+    method public long getColor(android.content.Context context);
+  }
+
+  public final class ColorProviderKt {
+    method public static androidx.glance.unit.ColorProvider ColorProvider(long color);
+  }
+
+}
+
diff --git a/glance/glance/build.gradle b/glance/glance/build.gradle
index b8fb797..68ec157 100644
--- a/glance/glance/build.gradle
+++ b/glance/glance/build.gradle
@@ -30,7 +30,7 @@
 dependencies {
 
     api("androidx.annotation:annotation:1.2.0")
-    api("androidx.compose.runtime:runtime:1.1.1")
+    api("androidx.compose.runtime:runtime:1.2.1")
     api("androidx.compose.ui:ui-graphics:1.1.1")
     api("androidx.compose.ui:ui-unit:1.1.1")
     api("androidx.datastore:datastore-core:1.0.0")
@@ -41,7 +41,6 @@
     implementation("androidx.work:work-runtime:2.7.1")
     implementation("androidx.work:work-runtime-ktx:2.7.1")
     implementation(libs.kotlinStdlib)
-    implementation(project(":compose:runtime:runtime"))
 
     // Force upgrade since 1.2.0 is not compatible with latest lint.
     implementation("androidx.annotation:annotation-experimental:1.3.0")
@@ -66,6 +65,7 @@
 
     androidTestImplementation('androidx.test:monitor:1.5.0')
     androidTestImplementation('androidx.core:core-ktx:1.7.0')
+    androidTestImplementation("androidx.room:room-runtime:2.4.3")
     androidTestImplementation("androidx.work:work-testing:2.7.1")
     androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
     androidTestImplementation(libs.kotlinCoroutinesTest)
diff --git a/glance/glance/src/androidAndroidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt b/glance/glance/src/androidAndroidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt
index 9db9374..78fc16b 100644
--- a/glance/glance/src/androidAndroidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt
+++ b/glance/glance/src/androidAndroidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt
@@ -33,6 +33,7 @@
 import androidx.work.WorkManager
 import androidx.work.WorkerFactory
 import androidx.work.WorkerParameters
+import androidx.work.impl.WorkManagerImpl
 import androidx.work.testing.SynchronousExecutor
 import androidx.work.testing.WorkManagerTestInitHelper
 import com.google.common.truth.Truth.assertThat
@@ -115,6 +116,8 @@
         testScope.cancel()
         workerStateScope.cancel()
         WorkManager.getInstance(context).cancelAllWork()
+        // TODO(b/242026176): remove this once WorkManager allows closing the test database.
+        WorkManagerImpl.getInstance(context).workDatabase.close()
     }
 
     @Test
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 0d1f5e0..3431ba0 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
 # -----------------------------------------------------------------------------
 # All of the following should be updated in sync.
 # -----------------------------------------------------------------------------
-androidGradlePlugin = "8.1.0-alpha11"
+androidGradlePlugin = "8.1.0-beta01"
 # NOTE: When updating the lint version we also need to update the `api` version
 # supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "31.1.0-alpha11"
+androidLint = "31.1.0-beta01"
 # Once you have a chosen version of AGP to upgrade to, go to
 # https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2022.3.1.11"
+androidStudio = "2022.3.1.12"
 # -----------------------------------------------------------------------------
 
 androidGradlePluginMin = "7.0.4"
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt
index 36adf59..50ccb37 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt
@@ -37,6 +37,7 @@
 import java.util.concurrent.TimeUnit
 import kotlin.math.roundToInt
 import org.junit.Assert
+import org.junit.Assert.fail
 import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -623,6 +624,57 @@
         }
     }
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testReleaseRemovedSurfaceCallbacks() {
+        val callbacks = object : CanvasFrontBufferedRenderer.Callback<Any> {
+            override fun onDrawFrontBufferedLayer(
+                canvas: Canvas,
+                bufferWidth: Int,
+                bufferHeight: Int,
+                param: Any
+            ) {
+                // no-op
+            }
+
+            override fun onDrawMultiBufferedLayer(
+                canvas: Canvas,
+                bufferWidth: Int,
+                bufferHeight: Int,
+                params: Collection<Any>
+            ) {
+                // no-op
+            }
+        }
+        var renderer: CanvasFrontBufferedRenderer<Any>? = null
+        var surfaceView: FrontBufferedRendererTestActivity.TestSurfaceView? = null
+        val createLatch = CountDownLatch(1)
+        ActivityScenario.launch(FrontBufferedRendererTestActivity::class.java)
+            .moveToState(Lifecycle.State.CREATED)
+            .onActivity {
+                surfaceView = it.getSurfaceView()
+                renderer = CanvasFrontBufferedRenderer(surfaceView!!, callbacks)
+                createLatch.countDown()
+            }
+
+        Assert.assertTrue(createLatch.await(3000, TimeUnit.MILLISECONDS))
+        // Capture surfaceView with local val to avoid Kotlin warnings regarding the surfaceView
+        // parameter changing potentially
+        val resolvedSurfaceView = surfaceView
+        try {
+            if (resolvedSurfaceView != null) {
+                Assert.assertEquals(1, resolvedSurfaceView.getCallbackCount())
+                renderer?.release(true)
+                renderer = null
+                Assert.assertEquals(0, resolvedSurfaceView.getCallbackCount())
+            } else {
+                fail("Unable to resolve SurfaceView, was the Activity created?")
+            }
+        } finally {
+            renderer?.release(true)
+        }
+    }
+
     @RequiresApi(Build.VERSION_CODES.Q)
     private fun CanvasFrontBufferedRenderer<*>?.blockingRelease(timeoutMillis: Long = 3000) {
         if (this != null) {
@@ -640,7 +692,13 @@
         // See "b/277225133" these tests pass on cuttlefish + other devices but fail for some reason
         // FTL configured API level 33 emulator instances
         // Additionally some cuttlefish instances don't support rotation based testing (b/277764242)
-        !(Build.MODEL.contains("gphone") && Build.VERSION.SDK_INT == 33) &&
-            !(Build.MODEL.contains("Cuttlefish") &&
-                (Build.VERSION.SDK_INT == 30 || BuildCompat.isAtLeastV()))
+        isSupportedGphone() && isSupportedCuttlefish()
+
+    private fun isSupportedGphone() =
+        !(Build.MODEL.contains("gphone") &&
+            (Build.VERSION.SDK_INT == 33 || Build.VERSION.SDK_INT == 30))
+
+    private fun isSupportedCuttlefish() =
+        !(Build.MODEL.contains("Cuttlefish") &&
+            (Build.VERSION.SDK_INT == 30 || BuildCompat.isAtLeastV()))
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/FrontBufferedRendererTestActivity.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/FrontBufferedRendererTestActivity.kt
index addcfff..9fae68f 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/FrontBufferedRendererTestActivity.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/FrontBufferedRendererTestActivity.kt
@@ -17,24 +17,60 @@
 package androidx.graphics.lowlatency
 
 import android.app.Activity
+import android.content.Context
 import android.os.Bundle
+import android.view.SurfaceHolder
 import android.view.SurfaceView
 import android.view.ViewGroup
 
 class FrontBufferedRendererTestActivity : Activity() {
 
-    private lateinit var mSurfaceView: SurfaceView
+    private lateinit var mSurfaceView: TestSurfaceView
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        val surfaceView = SurfaceView(this).also { mSurfaceView = it }
+        val surfaceView = TestSurfaceView(this).also { mSurfaceView = it }
         setContentView(surfaceView, ViewGroup.LayoutParams(WIDTH, HEIGHT))
     }
 
-    fun getSurfaceView(): SurfaceView = mSurfaceView
+    fun getSurfaceView(): TestSurfaceView = mSurfaceView
 
     companion object {
         const val WIDTH = 100
         const val HEIGHT = 100
     }
+
+    class TestSurfaceView(context: Context) : SurfaceView(context) {
+
+        private var mHolderWrapper: HolderWrapper? = null
+
+        override fun getHolder(): SurfaceHolder {
+            var wrapper = mHolderWrapper
+            if (wrapper == null) {
+                wrapper = HolderWrapper(super.getHolder()).also { mHolderWrapper = it }
+            }
+            return wrapper
+        }
+
+        fun getCallbackCount(): Int = mHolderWrapper?.mCallbacks?.size ?: 0
+
+        class HolderWrapper(val wrapped: SurfaceHolder) : SurfaceHolder by wrapped {
+
+            val mCallbacks = ArrayList<SurfaceHolder.Callback>()
+
+            override fun addCallback(callback: SurfaceHolder.Callback) {
+                if (!mCallbacks.contains(callback)) {
+                    mCallbacks.add(callback)
+                    wrapped.addCallback(callback)
+                }
+            }
+
+            override fun removeCallback(callback: SurfaceHolder.Callback) {
+                if (mCallbacks.contains(callback)) {
+                    mCallbacks.remove(callback)
+                    wrapped.removeCallback(callback)
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt
index 15fbf2e..a849854 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt
@@ -25,6 +25,7 @@
 import android.view.SurfaceHolder
 import android.view.SurfaceView
 import androidx.annotation.RequiresApi
+import androidx.graphics.opengl.GLRenderer
 import androidx.graphics.opengl.egl.EGLManager
 import androidx.graphics.surface.SurfaceControlCompat
 import androidx.graphics.surface.SurfaceControlUtils
@@ -37,9 +38,11 @@
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
+import kotlin.IllegalStateException
 import kotlin.math.roundToInt
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertThrows
 import org.junit.Assert.assertTrue
 import org.junit.Assert.fail
 import org.junit.Ignore
@@ -1218,6 +1221,92 @@
         }
     }
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testReleaseRemovedSurfaceCallbacks() {
+        val callbacks = object : GLFrontBufferedRenderer.Callback<Any> {
+            override fun onDrawFrontBufferedLayer(
+                eglManager: EGLManager,
+                bufferInfo: BufferInfo,
+                transform: FloatArray,
+                param: Any
+            ) {
+                // NO-OP
+            }
+
+            override fun onDrawMultiBufferedLayer(
+                eglManager: EGLManager,
+                bufferInfo: BufferInfo,
+                transform: FloatArray,
+                params: Collection<Any>
+            ) {
+                // NO-OP
+            }
+        }
+        var renderer: GLFrontBufferedRenderer<Any>? = null
+        var surfaceView: FrontBufferedRendererTestActivity.TestSurfaceView? = null
+        val createLatch = CountDownLatch(1)
+        ActivityScenario.launch(FrontBufferedRendererTestActivity::class.java)
+            .moveToState(Lifecycle.State.CREATED)
+            .onActivity {
+                surfaceView = it.getSurfaceView()
+                renderer = GLFrontBufferedRenderer(surfaceView!!, callbacks)
+                createLatch.countDown()
+            }
+
+        assertTrue(createLatch.await(3000, TimeUnit.MILLISECONDS))
+        // Capture surfaceView with local val to avoid Kotlin warnings regarding the surfaceView
+        // parameter changing potentially
+        val resolvedSurfaceView = surfaceView
+        try {
+            if (resolvedSurfaceView != null) {
+                assertEquals(1, resolvedSurfaceView.getCallbackCount())
+                val releaseLatch = CountDownLatch(1)
+                renderer!!.release(true) {
+                    releaseLatch.countDown()
+                }
+                assertTrue(releaseLatch.await(3000, TimeUnit.MILLISECONDS))
+                assertEquals(0, resolvedSurfaceView.getCallbackCount())
+                renderer = null
+            } else {
+                fail("Unable to resolve SurfaceView, was the test Activity created?")
+            }
+        } finally {
+            renderer?.blockingRelease()
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testGLFrontBufferedRendererCreationFromUnstartedGLRenderer() {
+        val callbacks = object : GLFrontBufferedRenderer.Callback<Any> {
+            override fun onDrawFrontBufferedLayer(
+                eglManager: EGLManager,
+                bufferInfo: BufferInfo,
+                transform: FloatArray,
+                param: Any
+            ) {
+                // NO-OP
+            }
+
+            override fun onDrawMultiBufferedLayer(
+                eglManager: EGLManager,
+                bufferInfo: BufferInfo,
+                transform: FloatArray,
+                params: Collection<Any>
+            ) {
+                // NO-OP
+            }
+        }
+        ActivityScenario.launch(FrontBufferedRendererTestActivity::class.java)
+            .moveToState(Lifecycle.State.CREATED)
+            .onActivity {
+                assertThrows(IllegalStateException::class.java) {
+                    GLFrontBufferedRenderer(it.getSurfaceView(), callbacks, GLRenderer())
+                }
+            }
+    }
+
     @RequiresApi(Build.VERSION_CODES.Q)
     private fun GLFrontBufferedRenderer<*>?.blockingRelease(timeoutMillis: Long = 3000) {
         if (this != null) {
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt
index 98cd2bc5..3a54bb1 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt
@@ -120,132 +120,133 @@
     private var inverse = BufferTransformHintResolver.UNKNOWN_TRANSFORM
     private val mBufferTransform = BufferTransformer()
     private val mParentLayerTransform = android.graphics.Matrix()
+    private val mHolderCallback = object : SurfaceHolder.Callback2 {
+
+        private var mWidth = -1
+        private var mHeight = -1
+
+        private var transformHint = BufferTransformHintResolver.UNKNOWN_TRANSFORM
+
+        private val mTransformResolver = BufferTransformHintResolver()
+
+        override fun surfaceCreated(p0: SurfaceHolder) {
+            // NO-OP
+        }
+
+        override fun surfaceChanged(
+            holder: SurfaceHolder,
+            format: Int,
+            width: Int,
+            height: Int
+        ) {
+            mWidth = width
+            mHeight = height
+            releaseInternal(true)
+            transformHint = mTransformResolver.getBufferTransformHint(surfaceView)
+            inverse = mBufferTransform.invertBufferTransform(transformHint)
+            mBufferTransform.computeTransform(width, height, inverse)
+            updateMatrixTransform(width.toFloat(), height.toFloat(), inverse)
+
+            mPersistedCanvasRenderer = SingleBufferedCanvasRenderer.create<T>(
+                width,
+                height,
+                mBufferTransform,
+                mExecutor,
+                object : SingleBufferedCanvasRenderer.RenderCallbacks<T> {
+
+                    override fun render(canvas: Canvas, width: Int, height: Int, param: T) {
+                        callback.onDrawFrontBufferedLayer(canvas, width, height, param)
+                    }
+
+                    @SuppressLint("WrongConstant")
+                    override fun onBufferReady(
+                        hardwareBuffer: HardwareBuffer,
+                        syncFenceCompat: SyncFenceCompat?
+                    ) {
+                        mPersistedCanvasRenderer?.isVisible = true
+                        mFrontBufferSurfaceControl?.let { frontBufferSurfaceControl ->
+                            val transaction = SurfaceControlCompat.Transaction()
+                                .setLayer(frontBufferSurfaceControl, Integer.MAX_VALUE)
+                                .setBuffer(
+                                    frontBufferSurfaceControl,
+                                    hardwareBuffer,
+                                    syncFenceCompat
+                                )
+                                .setVisibility(frontBufferSurfaceControl, true)
+                                .reparent(frontBufferSurfaceControl, mParentSurfaceControl)
+                            if (inverse != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
+                                transaction.setBufferTransform(
+                                    frontBufferSurfaceControl,
+                                    inverse
+                                )
+                            }
+                            callback.onFrontBufferedLayerRenderComplete(
+                                frontBufferSurfaceControl, transaction)
+                            transaction.commit()
+                            syncFenceCompat?.close()
+                        }
+                    }
+                })
+
+            val parentSurfaceControl = SurfaceControlCompat.Builder()
+                .setParent(surfaceView)
+                .setName("MultiBufferedLayer")
+                .build()
+                .apply {
+                    // SurfaceControl is not visible by default so make it visible right
+                    // after creation
+                    SurfaceControlCompat.Transaction()
+                        .setVisibility(this, true)
+                        .commit()
+                }
+
+            val multiBufferNode = RenderNode("MultiBufferNode").apply {
+                setPosition(0, 0, mBufferTransform.glWidth, mBufferTransform.glHeight)
+                mMultiBufferNode = this
+            }
+            mMultiBufferedCanvasRenderer = MultiBufferedCanvasRenderer(
+                multiBufferNode,
+                mBufferTransform.glWidth,
+                mBufferTransform.glHeight
+            )
+
+            mFrontBufferSurfaceControl = SurfaceControlCompat.Builder()
+                .setParent(parentSurfaceControl)
+                .setName("FrontBufferedLayer")
+                .build()
+
+            mParentSurfaceControl = parentSurfaceControl
+        }
+
+        override fun surfaceDestroyed(p0: SurfaceHolder) {
+            releaseInternal(true)
+        }
+
+        override fun surfaceRedrawNeeded(holder: SurfaceHolder) {
+            val latch = CountDownLatch(1)
+            surfaceRedrawNeededAsync(holder) {
+                latch.countDown()
+            }
+            latch.await()
+        }
+
+        override fun surfaceRedrawNeededAsync(
+            holder: SurfaceHolder,
+            drawingFinished: Runnable
+        ) {
+            val renderer = mMultiBufferedCanvasRenderer
+            if (renderer != null) {
+                renderer.renderFrame(mExecutor) { buffer ->
+                    setParentSurfaceControlBuffer(buffer, drawingFinished)
+                }
+            } else {
+                drawingFinished.run()
+            }
+        }
+    }
 
     init {
-        surfaceView.holder.addCallback(object : SurfaceHolder.Callback2 {
-
-            private var mWidth = -1
-            private var mHeight = -1
-
-            private var transformHint = BufferTransformHintResolver.UNKNOWN_TRANSFORM
-
-            private val mTransformResolver = BufferTransformHintResolver()
-
-            override fun surfaceCreated(p0: SurfaceHolder) {
-                // NO-OP
-            }
-
-            override fun surfaceChanged(
-                holder: SurfaceHolder,
-                format: Int,
-                width: Int,
-                height: Int
-            ) {
-                mWidth = width
-                mHeight = height
-                releaseInternal(true)
-                transformHint = mTransformResolver.getBufferTransformHint(surfaceView)
-                inverse = mBufferTransform.invertBufferTransform(transformHint)
-                mBufferTransform.computeTransform(width, height, inverse)
-                updateMatrixTransform(width.toFloat(), height.toFloat(), inverse)
-
-                mPersistedCanvasRenderer = SingleBufferedCanvasRenderer.create<T>(
-                    width,
-                    height,
-                    mBufferTransform,
-                    mExecutor,
-                    object : SingleBufferedCanvasRenderer.RenderCallbacks<T> {
-
-                        override fun render(canvas: Canvas, width: Int, height: Int, param: T) {
-                            callback.onDrawFrontBufferedLayer(canvas, width, height, param)
-                        }
-
-                        @SuppressLint("WrongConstant")
-                        override fun onBufferReady(
-                            hardwareBuffer: HardwareBuffer,
-                            syncFenceCompat: SyncFenceCompat?
-                        ) {
-                            mPersistedCanvasRenderer?.isVisible = true
-                            mFrontBufferSurfaceControl?.let { frontBufferSurfaceControl ->
-                                val transaction = SurfaceControlCompat.Transaction()
-                                    .setLayer(frontBufferSurfaceControl, Integer.MAX_VALUE)
-                                    .setBuffer(
-                                        frontBufferSurfaceControl,
-                                        hardwareBuffer,
-                                        syncFenceCompat
-                                    )
-                                    .setVisibility(frontBufferSurfaceControl, true)
-                                    .reparent(frontBufferSurfaceControl, mParentSurfaceControl)
-                                if (inverse != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
-                                    transaction.setBufferTransform(
-                                        frontBufferSurfaceControl,
-                                        inverse
-                                    )
-                                }
-                                callback.onFrontBufferedLayerRenderComplete(
-                                    frontBufferSurfaceControl, transaction)
-                                transaction.commit()
-                                syncFenceCompat?.close()
-                            }
-                        }
-                    })
-
-                val parentSurfaceControl = SurfaceControlCompat.Builder()
-                    .setParent(surfaceView)
-                    .setName("MultiBufferedLayer")
-                    .build()
-                    .apply {
-                        // SurfaceControl is not visible by default so make it visible right
-                        // after creation
-                        SurfaceControlCompat.Transaction()
-                            .setVisibility(this, true)
-                            .commit()
-                    }
-
-                val multiBufferNode = RenderNode("MultiBufferNode").apply {
-                    setPosition(0, 0, mBufferTransform.glWidth, mBufferTransform.glHeight)
-                    mMultiBufferNode = this
-                }
-                mMultiBufferedCanvasRenderer = MultiBufferedCanvasRenderer(
-                    multiBufferNode,
-                    mBufferTransform.glWidth,
-                    mBufferTransform.glHeight
-                )
-
-                mFrontBufferSurfaceControl = SurfaceControlCompat.Builder()
-                    .setParent(parentSurfaceControl)
-                    .setName("FrontBufferedLayer")
-                    .build()
-
-                mParentSurfaceControl = parentSurfaceControl
-            }
-
-            override fun surfaceDestroyed(p0: SurfaceHolder) {
-                releaseInternal(true)
-            }
-
-            override fun surfaceRedrawNeeded(holder: SurfaceHolder) {
-                val latch = CountDownLatch(1)
-                surfaceRedrawNeededAsync(holder) {
-                    latch.countDown()
-                }
-                latch.await()
-            }
-
-            override fun surfaceRedrawNeededAsync(
-                holder: SurfaceHolder,
-                drawingFinished: Runnable
-            ) {
-                val renderer = mMultiBufferedCanvasRenderer
-                if (renderer != null) {
-                    renderer.renderFrame(mExecutor) { buffer ->
-                        setParentSurfaceControlBuffer(buffer, drawingFinished)
-                    }
-                } else {
-                    drawingFinished.run()
-                }
-            }
-        })
+        surfaceView.holder.addCallback(mHolderCallback)
     }
 
     private inline fun RenderNode.record(block: (canvas: Canvas) -> Unit): RenderNode {
@@ -480,6 +481,7 @@
     @JvmOverloads
     fun release(cancelPending: Boolean, onReleaseComplete: (() -> Unit)? = null) {
         if (!mIsReleased) {
+            surfaceView.holder.removeCallback(mHolderCallback)
             releaseInternal(cancelPending) {
                 onReleaseComplete?.invoke()
                 mExecutor.shutdown()
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
index af54b29..65a5a40 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
@@ -35,6 +35,7 @@
 import androidx.hardware.SyncFenceCompat
 import androidx.opengl.EGLExt.Companion.EGL_ANDROID_NATIVE_FENCE_SYNC
 import androidx.opengl.EGLExt.Companion.EGL_KHR_FENCE_SYNC
+import java.lang.IllegalStateException
 import java.util.concurrent.ConcurrentLinkedQueue
 import java.util.concurrent.Executors
 
@@ -288,6 +289,11 @@
         } else {
             // ... otherwise use the [GLRenderer] that is being provided for us
             mIsManagingGLRenderer = false
+            if (!glRenderer.isRunning()) {
+                throw IllegalStateException("The provided GLRenderer must be running prior to " +
+                    "creation of GLFrontBufferedRenderer, " +
+                    "did you forget to call GLRenderer#start()?")
+            }
             glRenderer
         }
         renderer.registerEGLContextCallback(mContextCallbacks)
@@ -496,38 +502,27 @@
      * release SurfaceControl instances
      */
     internal fun detachTargets(cancelPending: Boolean, onReleaseComplete: (() -> Unit)? = null) {
-        // Wrap the callback into a separate lambda to ensure it is invoked only after
-        // both the front and multi buffered layer target renderers are detached
-        var callbackCount = 0
-        var expectedCount = 0
-        if (mFrontBufferedRenderTarget?.isAttached() == true) {
-            expectedCount++
-        }
+        // GLRenderer processes requests in order on a single thread. So detach the corresponding
+        // render targets then queue a request to teardown all resources
+        mFrontBufferedRenderTarget?.detach(cancelPending)
+        mMultiBufferedLayerRenderTarget?.detach(cancelPending)
 
-        if (mMultiBufferedLayerRenderTarget?.isAttached() == true) {
-            expectedCount++
-        }
         val frontBufferedLayerSurfaceControl = mFrontBufferedLayerSurfaceControl
-        val wrappedCallback: (GLRenderer.RenderTarget) -> Unit = {
-            callbackCount++
-            if (callbackCount >= expectedCount) {
-                mBufferPool?.let { releaseBuffers(it) }
-                clearParamQueues()
-
-                frontBufferedLayerSurfaceControl?.let {
-                    val transaction = SurfaceControlCompat.Transaction()
-                        .reparent(it, null)
-                    mParentRenderLayer.release(transaction)
-                    transaction.commit()
-                    it.release()
-                }
-
-                onReleaseComplete?.invoke()
-            }
-        }
         mFrontBufferedLayerSurfaceControl = null
-        mFrontBufferedRenderTarget?.detach(cancelPending, wrappedCallback)
-        mMultiBufferedLayerRenderTarget?.detach(cancelPending, wrappedCallback)
+        mGLRenderer.execute {
+            mBufferPool?.let { releaseBuffers(it) }
+            clearParamQueues()
+
+            val transaction = SurfaceControlCompat.Transaction()
+            if (frontBufferedLayerSurfaceControl != null) {
+                transaction.reparent(frontBufferedLayerSurfaceControl, null)
+            }
+            mParentRenderLayer.release(transaction)
+            transaction.commit()
+            frontBufferedLayerSurfaceControl?.release()
+
+            onReleaseComplete?.invoke()
+        }
         mFrontBufferedRenderTarget = null
         mMultiBufferedLayerRenderTarget = null
         mWidth = -1
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt
index b2407a3..ad99c0c 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt
@@ -48,36 +48,38 @@
 
     private val mTransformResolver = BufferTransformHintResolver()
 
-    private var transformHint = BufferTransformHintResolver.UNKNOWN_TRANSFORM
-    private var inverse = BufferTransformHintResolver.UNKNOWN_TRANSFORM
-    init {
-        surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
+    private var mTransformHint = BufferTransformHintResolver.UNKNOWN_TRANSFORM
+    private var mInverse = BufferTransformHintResolver.UNKNOWN_TRANSFORM
+    private val mHolderCallback = object : SurfaceHolder.Callback {
 
-            override fun surfaceCreated(holder: SurfaceHolder) {
-                // NO-OP wait on surfaceChanged callback
-            }
+        override fun surfaceCreated(holder: SurfaceHolder) {
+            // NO-OP wait on surfaceChanged callback
+        }
 
-            override fun surfaceChanged(
-                holder: SurfaceHolder,
-                format: Int,
-                width: Int,
-                height: Int
-            ) {
-                transformHint = mTransformResolver.getBufferTransformHint(surfaceView)
-                inverse = mBufferTransform.invertBufferTransform(transformHint)
-                mBufferTransform.computeTransform(width, height, inverse)
-                mParentSurfaceControl?.release()
-                mParentSurfaceControl = createDoubleBufferedSurfaceControl()
-                mLayerCallback?.onSizeChanged(width, height)
-            }
+        override fun surfaceChanged(
+            holder: SurfaceHolder,
+            format: Int,
+            width: Int,
+            height: Int
+        ) {
+            mTransformHint = mTransformResolver.getBufferTransformHint(surfaceView)
+            mInverse = mBufferTransform.invertBufferTransform(mTransformHint)
+            mBufferTransform.computeTransform(width, height, mInverse)
+            mParentSurfaceControl?.release()
+            mParentSurfaceControl = createDoubleBufferedSurfaceControl()
+            mLayerCallback?.onSizeChanged(width, height)
+        }
 
-            override fun surfaceDestroyed(p0: SurfaceHolder) {
-                mLayerCallback?.onLayerDestroyed()
-            }
-        })
+        override fun surfaceDestroyed(p0: SurfaceHolder) {
+            mLayerCallback?.onLayerDestroyed()
+        }
     }
 
-    override fun getInverseBufferTransform(): Int = inverse
+    init {
+        surfaceView.holder.addCallback(mHolderCallback)
+    }
+
+    override fun getInverseBufferTransform(): Int = mInverse
 
     override fun getBufferWidth(): Int = mBufferTransform.glWidth
 
@@ -151,8 +153,8 @@
                             .setBuffer(sc, frameBuffer.hardwareBuffer, syncFenceCompat) {
                                 mLayerCallback?.getFrameBufferPool()?.release(frameBuffer)
                             }
-                        if (transformHint != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
-                            transaction.setBufferTransform(sc, inverse)
+                        if (mTransformHint != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
+                            transaction.setBufferTransform(sc, mInverse)
                         }
 
                         renderLayerCallback.onMultiBufferedLayerRenderComplete(
@@ -197,8 +199,8 @@
         mRenderTarget?.requestRender()
     }
 
-    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     override fun release(transaction: SurfaceControlCompat.Transaction) {
+        surfaceView.holder.removeCallback(mHolderCallback)
         mParentSurfaceControl?.let {
             transaction.reparent(it, null)
             it.release()
diff --git a/health/connect/connect-client/build.gradle b/health/connect/connect-client/build.gradle
index 8a8757a..06b657b 100644
--- a/health/connect/connect-client/build.gradle
+++ b/health/connect/connect-client/build.gradle
@@ -35,10 +35,7 @@
     // Add dependencies here
     api("androidx.activity:activity:1.2.0")
     api("androidx.annotation:annotation:1.2.0")
-    bundleInside(project(
-            path: ":health:connect:connect-client-proto",
-            configuration: "export"
-    ))
+    bundleInside(project(path: ":health:connect:connect-client-proto", configuration: "export"))
     implementation(libs.guavaListenableFuture)
     implementation(libs.guavaAndroid)
     implementation(libs.kotlinCoroutinesAndroid)
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseLap.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseLap.kt
new file mode 100644
index 0000000..08aa1fc
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseLap.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.health.connect.client.records
+
+import androidx.annotation.RestrictTo
+import androidx.health.connect.client.units.Length
+import java.time.Instant
+
+/**
+ * Captures the time of a lap within an exercise session.
+ *
+ * <p>Each lap contains the start and end time and optional [Length] of the lap (e.g. pool
+ * length while swimming or a track lap while running). There may or may not be direct correlation
+ * with [ExerciseSegment] start and end times, e.g. [ExerciseSessionRecord] of type
+ * running without any segments can be divided into laps of different lengths.
+ *
+ * @see ExerciseSessionRecord
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class ExerciseLap(
+    public val startTime: Instant,
+    public val endTime: Instant,
+    /** Lap length in [Length] unit. Optional field. Valid range: 0-1000000 meters. */
+    public val length: Length? = null,
+) {
+    init {
+        require(startTime.isBefore(endTime)) { "startTime must be before endTime." }
+        if (length != null) {
+            require(length.inMeters in 0.0..1000000.0) { "length valid range: 0-1000000." }
+        }
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is ExerciseLap) return false
+
+        if (startTime != other.startTime) return false
+        if (endTime != other.endTime) return false
+        if (length != other.length) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = 0
+        result = 31 * result + startTime.hashCode()
+        result = 31 * result + endTime.hashCode()
+        result = 31 * result + length.hashCode()
+        return result
+    }
+}
\ No newline at end of file
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseRoute.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseRoute.kt
new file mode 100644
index 0000000..7608b6a
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseRoute.kt
@@ -0,0 +1,123 @@
+/*
+ * 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.health.connect.client.records
+
+import androidx.annotation.RestrictTo
+import androidx.health.connect.client.units.Length
+import java.time.Instant
+
+/**
+ * Captures a route associated with an exercise session a user does.
+ *
+ * Contains a sequence of location points, with timestamps, which do not have to be in order.
+ *
+ * Location points contain a timestamp, longitude, latitude, and optionally altitude, horizontal and
+ * vertical accuracy.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class ExerciseRoute(route: List<Location>) {
+    public val route: List<Location> = route.sortedWith { a, b -> a.time.compareTo(b.time) }
+
+    init {
+        for (i in 0 until this.route.lastIndex) {
+            require(this.route[i].time.isBefore(this.route[i + 1].time))
+        }
+    }
+    internal fun isWithin(startTime: Instant, endTime: Instant): Boolean {
+        // startTime is inclusive, endTime is exclusive
+        return !route.first().time.isBefore(startTime) && route.last().time.isBefore(endTime)
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is ExerciseRoute) return false
+
+        return route == other.route
+    }
+
+    override fun hashCode(): Int {
+        return route.hashCode()
+    }
+
+    /**
+     * Represents a single location point recorded during an exercise.
+     *
+     * @param time The point in time when the location was recorded; Required field.
+     * @param latitude Latitude of the location point; Required field; Valid range [-90; 90]
+     * @param longitude Longitude of the location point; Required field; Valid range [-180; 180]
+     * @param altitude in [Length] unit. Optional field. Valid range: non-negative numbers.
+     * @param horizontalAccuracy in [Length] unit. Optional field. Valid range: non-negative
+     *   numbers.
+     * @param verticalAccuracy in [Length] unit. Optional field. Valid range: non-negative numbers.
+     * @see ExerciseRoute
+     */
+    public class Location(
+        val time: Instant,
+        val latitude: Double,
+        val longitude: Double,
+        val horizontalAccuracy: Length? = null,
+        val verticalAccuracy: Length? = null,
+        val altitude: Length? = null
+    ) {
+
+        companion object {
+            private const val MIN_LONGITUDE = -180.0
+            private const val MAX_LONGITUDE = 180.0
+            private const val MIN_LATITUDE = -90.0
+            private const val MAX_LATITUDE = 90.0
+        }
+
+        init {
+            latitude.requireNotLess(other = MIN_LATITUDE, name = "latitude")
+            latitude.requireNotMore(other = MAX_LATITUDE, name = "latitude")
+            longitude.requireNotLess(other = MIN_LONGITUDE, name = "longitude")
+            longitude.requireNotMore(other = MAX_LONGITUDE, name = "longitude")
+            horizontalAccuracy?.requireNotLess(
+                other = horizontalAccuracy.zero(),
+                name = "horizontalAccuracy"
+            )
+            verticalAccuracy?.requireNotLess(
+                other = verticalAccuracy.zero(),
+                name = "verticalAccuracy"
+            )
+        }
+
+        override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (other !is Location) return false
+
+            if (time != other.time) return false
+            if (latitude != other.latitude) return false
+            if (longitude != other.longitude) return false
+            if (horizontalAccuracy != other.horizontalAccuracy) return false
+            if (verticalAccuracy != other.verticalAccuracy) return false
+            if (altitude != other.altitude) return false
+
+            return true
+        }
+
+        override fun hashCode(): Int {
+            var result = time.hashCode()
+            result = 31 * result + latitude.hashCode()
+            result = 31 * result + longitude.hashCode()
+            result = 31 * result + (horizontalAccuracy?.hashCode() ?: 0)
+            result = 31 * result + (verticalAccuracy?.hashCode() ?: 0)
+            result = 31 * result + (altitude?.hashCode() ?: 0)
+            return result
+        }
+    }
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSegment.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSegment.kt
new file mode 100644
index 0000000..968aeec
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSegment.kt
@@ -0,0 +1,350 @@
+/*
+ * 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.health.connect.client.records
+
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
+import java.time.Instant
+
+/**
+ * Represents particular exercise within an exercise session.
+ *
+ * <p>Each segment contains start and end time of the exercise, exercise type and optional number of
+ * repetitions.
+ *
+ * @see ExerciseSessionRecord
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class ExerciseSegment(
+    public val startTime: Instant,
+    public val endTime: Instant,
+    @property:ExerciseSegmentTypes public val segmentType: Int,
+    public val repetitions: Int = 0,
+) {
+    init {
+        require(startTime.isBefore(endTime)) { "startTime must be before endTime." }
+        require(repetitions >= 0) { "repetitions can not be negative." }
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is ExerciseSegment) return false
+
+        if (startTime != other.startTime) return false
+        if (endTime != other.endTime) return false
+        if (segmentType != other.segmentType) return false
+        if (repetitions != other.repetitions) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = 0
+        result = 31 * result + startTime.hashCode()
+        result = 31 * result + endTime.hashCode()
+        result = 31 * result + segmentType.hashCode()
+        result = 31 * result + repetitions.hashCode()
+        return result
+    }
+
+    internal fun isCompatibleWith(sessionType: Int): Boolean {
+        if (UNIVERSAL_SESSION_TYPES.contains(sessionType)) {
+            return true
+        }
+        if (UNIVERSAL_SEGMENTS.contains(segmentType)) {
+            return true
+        }
+        if (!SESSION_TO_SEGMENTS_MAPPING.contains(sessionType)) {
+            return false
+        }
+        return SESSION_TO_SEGMENTS_MAPPING[sessionType]!!.contains(segmentType)
+    }
+
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    companion object {
+        /** Next Id: 68. */
+        const val EXERCISE_SEGMENT_TYPE_UNKNOWN = 0
+        const val EXERCISE_SEGMENT_TYPE_ARM_CURL = 1
+        const val EXERCISE_SEGMENT_TYPE_BACK_EXTENSION = 2
+        const val EXERCISE_SEGMENT_TYPE_BALL_SLAM = 3
+        const val EXERCISE_SEGMENT_TYPE_BARBELL_SHOULDER_PRESS = 4
+        const val EXERCISE_SEGMENT_TYPE_BENCH_PRESS = 5
+        const val EXERCISE_SEGMENT_TYPE_BENCH_SIT_UP = 6
+        const val EXERCISE_SEGMENT_TYPE_BIKING = 7
+        const val EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY = 8
+        const val EXERCISE_SEGMENT_TYPE_BURPEE = 9
+        const val EXERCISE_SEGMENT_TYPE_CRUNCH = 10
+        const val EXERCISE_SEGMENT_TYPE_DEADLIFT = 11
+        const val EXERCISE_SEGMENT_TYPE_DOUBLE_ARM_TRICEPS_EXTENSION = 12
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_LEFT_ARM = 13
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_RIGHT_ARM = 14
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_FRONT_RAISE = 15
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_LATERAL_RAISE = 16
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_ROW = 17
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM = 18
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM = 19
+        const val EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_TWO_ARM = 20
+        const val EXERCISE_SEGMENT_TYPE_ELLIPTICAL = 21
+        const val EXERCISE_SEGMENT_TYPE_FORWARD_TWIST = 22
+        const val EXERCISE_SEGMENT_TYPE_FRONT_RAISE = 23
+        const val EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING = 24
+        const val EXERCISE_SEGMENT_TYPE_HIP_THRUST = 25
+        const val EXERCISE_SEGMENT_TYPE_HULA_HOOP = 26
+        const val EXERCISE_SEGMENT_TYPE_JUMPING_JACK = 27
+        const val EXERCISE_SEGMENT_TYPE_JUMP_ROPE = 28
+        const val EXERCISE_SEGMENT_TYPE_KETTLEBELL_SWING = 29
+        const val EXERCISE_SEGMENT_TYPE_LATERAL_RAISE = 30
+        const val EXERCISE_SEGMENT_TYPE_LAT_PULL_DOWN = 31
+        const val EXERCISE_SEGMENT_TYPE_LEG_CURL = 32
+        const val EXERCISE_SEGMENT_TYPE_LEG_EXTENSION = 33
+        const val EXERCISE_SEGMENT_TYPE_LEG_PRESS = 34
+        const val EXERCISE_SEGMENT_TYPE_LEG_RAISE = 35
+        const val EXERCISE_SEGMENT_TYPE_LUNGE = 36
+        const val EXERCISE_SEGMENT_TYPE_MOUNTAIN_CLIMBER = 37
+        const val EXERCISE_SEGMENT_TYPE_OTHER_WORKOUT = 38
+        const val EXERCISE_SEGMENT_TYPE_PAUSE = 39
+        const val EXERCISE_SEGMENT_TYPE_PILATES = 40
+        const val EXERCISE_SEGMENT_TYPE_PLANK = 41
+        const val EXERCISE_SEGMENT_TYPE_PULL_UP = 42
+        const val EXERCISE_SEGMENT_TYPE_PUNCH = 43
+        const val EXERCISE_SEGMENT_TYPE_REST = 44
+        const val EXERCISE_SEGMENT_TYPE_ROWING_MACHINE = 45
+        const val EXERCISE_SEGMENT_TYPE_RUNNING = 46
+        const val EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL = 47
+        const val EXERCISE_SEGMENT_TYPE_SHOULDER_PRESS = 48
+        const val EXERCISE_SEGMENT_TYPE_SINGLE_ARM_TRICEPS_EXTENSION = 49
+        const val EXERCISE_SEGMENT_TYPE_SIT_UP = 50
+        const val EXERCISE_SEGMENT_TYPE_SQUAT = 51
+        const val EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING = 52
+        const val EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE = 53
+        const val EXERCISE_SEGMENT_TYPE_STRETCHING = 54
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_BACKSTROKE = 55
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_BREASTSTROKE = 56
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_BUTTERFLY = 57
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_FREESTYLE = 58
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_MIXED = 59
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_OPEN_WATER = 60
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_OTHER = 61
+        const val EXERCISE_SEGMENT_TYPE_SWIMMING_POOL = 62
+        const val EXERCISE_SEGMENT_TYPE_UPPER_TWIST = 63
+        const val EXERCISE_SEGMENT_TYPE_WALKING = 64
+        const val EXERCISE_SEGMENT_TYPE_WEIGHTLIFTING = 65
+        const val EXERCISE_SEGMENT_TYPE_WHEELCHAIR = 66
+        const val EXERCISE_SEGMENT_TYPE_YOGA = 67
+
+        internal val UNIVERSAL_SESSION_TYPES = setOf(
+            ExerciseSessionRecord.EXERCISE_TYPE_BOOT_CAMP,
+            ExerciseSessionRecord.EXERCISE_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
+            ExerciseSessionRecord.EXERCISE_TYPE_OTHER_WORKOUT,
+        )
+
+        internal val UNIVERSAL_SEGMENTS = setOf(
+            EXERCISE_SEGMENT_TYPE_OTHER_WORKOUT,
+            EXERCISE_SEGMENT_TYPE_PAUSE,
+            EXERCISE_SEGMENT_TYPE_REST,
+            EXERCISE_SEGMENT_TYPE_STRETCHING,
+            EXERCISE_SEGMENT_TYPE_UNKNOWN,
+        )
+
+        internal val EXERCISE_SEGMENTS = setOf(
+            EXERCISE_SEGMENT_TYPE_ARM_CURL,
+            EXERCISE_SEGMENT_TYPE_BACK_EXTENSION,
+            EXERCISE_SEGMENT_TYPE_BALL_SLAM,
+            EXERCISE_SEGMENT_TYPE_BARBELL_SHOULDER_PRESS,
+            EXERCISE_SEGMENT_TYPE_BENCH_PRESS,
+            EXERCISE_SEGMENT_TYPE_BENCH_SIT_UP,
+            EXERCISE_SEGMENT_TYPE_BURPEE,
+            EXERCISE_SEGMENT_TYPE_CRUNCH,
+            EXERCISE_SEGMENT_TYPE_DEADLIFT,
+            EXERCISE_SEGMENT_TYPE_DOUBLE_ARM_TRICEPS_EXTENSION,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_LEFT_ARM,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_RIGHT_ARM,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_FRONT_RAISE,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_LATERAL_RAISE,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_ROW,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM,
+            EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_TWO_ARM,
+            EXERCISE_SEGMENT_TYPE_FORWARD_TWIST,
+            EXERCISE_SEGMENT_TYPE_FRONT_RAISE,
+            EXERCISE_SEGMENT_TYPE_HIP_THRUST,
+            EXERCISE_SEGMENT_TYPE_HULA_HOOP,
+            EXERCISE_SEGMENT_TYPE_JUMP_ROPE,
+            EXERCISE_SEGMENT_TYPE_JUMPING_JACK,
+            EXERCISE_SEGMENT_TYPE_KETTLEBELL_SWING,
+            EXERCISE_SEGMENT_TYPE_LATERAL_RAISE,
+            EXERCISE_SEGMENT_TYPE_LAT_PULL_DOWN,
+            EXERCISE_SEGMENT_TYPE_LEG_CURL,
+            EXERCISE_SEGMENT_TYPE_LEG_EXTENSION,
+            EXERCISE_SEGMENT_TYPE_LEG_PRESS,
+            EXERCISE_SEGMENT_TYPE_LEG_RAISE,
+            EXERCISE_SEGMENT_TYPE_LUNGE,
+            EXERCISE_SEGMENT_TYPE_MOUNTAIN_CLIMBER,
+            EXERCISE_SEGMENT_TYPE_PLANK,
+            EXERCISE_SEGMENT_TYPE_PULL_UP,
+            EXERCISE_SEGMENT_TYPE_PUNCH,
+            EXERCISE_SEGMENT_TYPE_SHOULDER_PRESS,
+            EXERCISE_SEGMENT_TYPE_SINGLE_ARM_TRICEPS_EXTENSION,
+            EXERCISE_SEGMENT_TYPE_SIT_UP,
+            EXERCISE_SEGMENT_TYPE_SQUAT,
+            EXERCISE_SEGMENT_TYPE_UPPER_TWIST,
+            EXERCISE_SEGMENT_TYPE_WEIGHTLIFTING
+        )
+        internal val SWIMMING_SEGMENTS = setOf(
+            EXERCISE_SEGMENT_TYPE_SWIMMING_BACKSTROKE,
+            EXERCISE_SEGMENT_TYPE_SWIMMING_BREASTSTROKE,
+            EXERCISE_SEGMENT_TYPE_SWIMMING_FREESTYLE,
+            EXERCISE_SEGMENT_TYPE_SWIMMING_BUTTERFLY,
+            EXERCISE_SEGMENT_TYPE_SWIMMING_MIXED,
+            EXERCISE_SEGMENT_TYPE_SWIMMING_OTHER
+        )
+
+        private val SESSION_TO_SEGMENTS_MAPPING = mapOf(
+            ExerciseSessionRecord.EXERCISE_TYPE_BIKING to setOf(EXERCISE_SEGMENT_TYPE_BIKING),
+            ExerciseSessionRecord.EXERCISE_TYPE_BIKING_STATIONARY to setOf(
+                EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_CALISTHENICS to EXERCISE_SEGMENTS,
+            ExerciseSessionRecord.EXERCISE_TYPE_ELLIPTICAL
+                to setOf(EXERCISE_SEGMENT_TYPE_ELLIPTICAL),
+            ExerciseSessionRecord.EXERCISE_TYPE_EXERCISE_CLASS to setOf(
+                EXERCISE_SEGMENT_TYPE_YOGA,
+                EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY,
+                EXERCISE_SEGMENT_TYPE_PILATES,
+                EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_GYMNASTICS to EXERCISE_SEGMENTS,
+            ExerciseSessionRecord.EXERCISE_TYPE_HIKING to setOf(
+                EXERCISE_SEGMENT_TYPE_WALKING,
+                EXERCISE_SEGMENT_TYPE_WHEELCHAIR
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_PILATES to setOf(EXERCISE_SEGMENT_TYPE_PILATES),
+            ExerciseSessionRecord.EXERCISE_TYPE_ROWING_MACHINE to setOf(
+                EXERCISE_SEGMENT_TYPE_ROWING_MACHINE
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_RUNNING to setOf(
+                EXERCISE_SEGMENT_TYPE_RUNNING,
+                EXERCISE_SEGMENT_TYPE_WALKING
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_RUNNING_TREADMILL to setOf(
+                EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_STRENGTH_TRAINING to EXERCISE_SEGMENTS,
+            ExerciseSessionRecord.EXERCISE_TYPE_STAIR_CLIMBING to setOf(
+                EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_STAIR_CLIMBING_MACHINE to setOf(
+                EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE
+            ),
+            ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_OPEN_WATER to buildSet {
+                add(EXERCISE_SEGMENT_TYPE_SWIMMING_OPEN_WATER)
+                addAll(SWIMMING_SEGMENTS)
+            },
+            ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_POOL to buildSet {
+                add(EXERCISE_SEGMENT_TYPE_SWIMMING_POOL)
+                addAll(SWIMMING_SEGMENTS)
+            },
+            ExerciseSessionRecord.EXERCISE_TYPE_WALKING to setOf(EXERCISE_SEGMENT_TYPE_WALKING),
+            ExerciseSessionRecord.EXERCISE_TYPE_WHEELCHAIR
+                to setOf(EXERCISE_SEGMENT_TYPE_WHEELCHAIR),
+            ExerciseSessionRecord.EXERCISE_TYPE_WEIGHTLIFTING to EXERCISE_SEGMENTS,
+            ExerciseSessionRecord.EXERCISE_TYPE_YOGA to setOf(EXERCISE_SEGMENT_TYPE_YOGA),
+        )
+
+        /**
+         * List of supported segment types on Health Platform.
+         *
+         * @suppress
+         */
+        @Retention(AnnotationRetention.SOURCE)
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
+        @IntDef(
+            value =
+            [
+                EXERCISE_SEGMENT_TYPE_UNKNOWN,
+                EXERCISE_SEGMENT_TYPE_BARBELL_SHOULDER_PRESS,
+                EXERCISE_SEGMENT_TYPE_BENCH_SIT_UP,
+                EXERCISE_SEGMENT_TYPE_BIKING,
+                EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_LEFT_ARM,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_RIGHT_ARM,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_FRONT_RAISE,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_LATERAL_RAISE,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_TWO_ARM,
+                EXERCISE_SEGMENT_TYPE_FORWARD_TWIST,
+                EXERCISE_SEGMENT_TYPE_ELLIPTICAL,
+                EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
+                EXERCISE_SEGMENT_TYPE_PILATES,
+                EXERCISE_SEGMENT_TYPE_ROWING_MACHINE,
+                EXERCISE_SEGMENT_TYPE_RUNNING,
+                EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL,
+                EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING,
+                EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE,
+                EXERCISE_SEGMENT_TYPE_STRETCHING,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_OPEN_WATER,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_POOL,
+                EXERCISE_SEGMENT_TYPE_UPPER_TWIST,
+                EXERCISE_SEGMENT_TYPE_WALKING,
+                EXERCISE_SEGMENT_TYPE_WEIGHTLIFTING,
+                EXERCISE_SEGMENT_TYPE_WHEELCHAIR,
+                EXERCISE_SEGMENT_TYPE_OTHER_WORKOUT,
+                EXERCISE_SEGMENT_TYPE_YOGA,
+                EXERCISE_SEGMENT_TYPE_ARM_CURL,
+                EXERCISE_SEGMENT_TYPE_BACK_EXTENSION,
+                EXERCISE_SEGMENT_TYPE_BALL_SLAM,
+                EXERCISE_SEGMENT_TYPE_BENCH_PRESS,
+                EXERCISE_SEGMENT_TYPE_BURPEE,
+                EXERCISE_SEGMENT_TYPE_CRUNCH,
+                EXERCISE_SEGMENT_TYPE_DEADLIFT,
+                EXERCISE_SEGMENT_TYPE_DOUBLE_ARM_TRICEPS_EXTENSION,
+                EXERCISE_SEGMENT_TYPE_DUMBBELL_ROW,
+                EXERCISE_SEGMENT_TYPE_FRONT_RAISE,
+                EXERCISE_SEGMENT_TYPE_HIP_THRUST,
+                EXERCISE_SEGMENT_TYPE_HULA_HOOP,
+                EXERCISE_SEGMENT_TYPE_JUMPING_JACK,
+                EXERCISE_SEGMENT_TYPE_JUMP_ROPE,
+                EXERCISE_SEGMENT_TYPE_KETTLEBELL_SWING,
+                EXERCISE_SEGMENT_TYPE_LATERAL_RAISE,
+                EXERCISE_SEGMENT_TYPE_LAT_PULL_DOWN,
+                EXERCISE_SEGMENT_TYPE_LEG_CURL,
+                EXERCISE_SEGMENT_TYPE_LEG_EXTENSION,
+                EXERCISE_SEGMENT_TYPE_LEG_PRESS,
+                EXERCISE_SEGMENT_TYPE_LEG_RAISE,
+                EXERCISE_SEGMENT_TYPE_LUNGE,
+                EXERCISE_SEGMENT_TYPE_MOUNTAIN_CLIMBER,
+                EXERCISE_SEGMENT_TYPE_PLANK,
+                EXERCISE_SEGMENT_TYPE_PULL_UP,
+                EXERCISE_SEGMENT_TYPE_PUNCH,
+                EXERCISE_SEGMENT_TYPE_SHOULDER_PRESS,
+                EXERCISE_SEGMENT_TYPE_SINGLE_ARM_TRICEPS_EXTENSION,
+                EXERCISE_SEGMENT_TYPE_SIT_UP,
+                EXERCISE_SEGMENT_TYPE_SQUAT,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_FREESTYLE,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_BACKSTROKE,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_BREASTSTROKE,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_BUTTERFLY,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_MIXED,
+                EXERCISE_SEGMENT_TYPE_SWIMMING_OTHER,
+                EXERCISE_SEGMENT_TYPE_REST,
+                EXERCISE_SEGMENT_TYPE_PAUSE,
+            ]
+        )
+        annotation class ExerciseSegmentTypes
+    }
+}
\ No newline at end of file
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSessionRecord.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSessionRecord.kt
index f2b31a1..c780c9c 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSessionRecord.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/ExerciseSessionRecord.kt
@@ -272,69 +272,69 @@
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     @IntDef(
         value =
-            [
-                EXERCISE_TYPE_BADMINTON,
-                EXERCISE_TYPE_BASEBALL,
-                EXERCISE_TYPE_BASKETBALL,
-                EXERCISE_TYPE_BIKING,
-                EXERCISE_TYPE_BIKING_STATIONARY,
-                EXERCISE_TYPE_BOOT_CAMP,
-                EXERCISE_TYPE_BOXING,
-                EXERCISE_TYPE_CALISTHENICS,
-                EXERCISE_TYPE_CRICKET,
-                EXERCISE_TYPE_DANCING,
-                EXERCISE_TYPE_ELLIPTICAL,
-                EXERCISE_TYPE_EXERCISE_CLASS,
-                EXERCISE_TYPE_FENCING,
-                EXERCISE_TYPE_FOOTBALL_AMERICAN,
-                EXERCISE_TYPE_FOOTBALL_AUSTRALIAN,
-                EXERCISE_TYPE_FRISBEE_DISC,
-                EXERCISE_TYPE_GOLF,
-                EXERCISE_TYPE_GUIDED_BREATHING,
-                EXERCISE_TYPE_GYMNASTICS,
-                EXERCISE_TYPE_HANDBALL,
-                EXERCISE_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
-                EXERCISE_TYPE_HIKING,
-                EXERCISE_TYPE_ICE_HOCKEY,
-                EXERCISE_TYPE_ICE_SKATING,
-                EXERCISE_TYPE_MARTIAL_ARTS,
-                EXERCISE_TYPE_PADDLING,
-                EXERCISE_TYPE_PARAGLIDING,
-                EXERCISE_TYPE_PILATES,
-                EXERCISE_TYPE_RACQUETBALL,
-                EXERCISE_TYPE_ROCK_CLIMBING,
-                EXERCISE_TYPE_ROLLER_HOCKEY,
-                EXERCISE_TYPE_ROWING,
-                EXERCISE_TYPE_ROWING_MACHINE,
-                EXERCISE_TYPE_RUGBY,
-                EXERCISE_TYPE_RUNNING,
-                EXERCISE_TYPE_RUNNING_TREADMILL,
-                EXERCISE_TYPE_SAILING,
-                EXERCISE_TYPE_SCUBA_DIVING,
-                EXERCISE_TYPE_SKATING,
-                EXERCISE_TYPE_SKIING,
-                EXERCISE_TYPE_SNOWBOARDING,
-                EXERCISE_TYPE_SNOWSHOEING,
-                EXERCISE_TYPE_SOCCER,
-                EXERCISE_TYPE_SOFTBALL,
-                EXERCISE_TYPE_SQUASH,
-                EXERCISE_TYPE_STAIR_CLIMBING,
-                EXERCISE_TYPE_STAIR_CLIMBING_MACHINE,
-                EXERCISE_TYPE_STRENGTH_TRAINING,
-                EXERCISE_TYPE_STRETCHING,
-                EXERCISE_TYPE_SURFING,
-                EXERCISE_TYPE_SWIMMING_OPEN_WATER,
-                EXERCISE_TYPE_SWIMMING_POOL,
-                EXERCISE_TYPE_TABLE_TENNIS,
-                EXERCISE_TYPE_TENNIS,
-                EXERCISE_TYPE_VOLLEYBALL,
-                EXERCISE_TYPE_WALKING,
-                EXERCISE_TYPE_WATER_POLO,
-                EXERCISE_TYPE_WEIGHTLIFTING,
-                EXERCISE_TYPE_WHEELCHAIR,
-                EXERCISE_TYPE_OTHER_WORKOUT,
-                EXERCISE_TYPE_YOGA,
-            ]
+        [
+            EXERCISE_TYPE_BADMINTON,
+            EXERCISE_TYPE_BASEBALL,
+            EXERCISE_TYPE_BASKETBALL,
+            EXERCISE_TYPE_BIKING,
+            EXERCISE_TYPE_BIKING_STATIONARY,
+            EXERCISE_TYPE_BOOT_CAMP,
+            EXERCISE_TYPE_BOXING,
+            EXERCISE_TYPE_CALISTHENICS,
+            EXERCISE_TYPE_CRICKET,
+            EXERCISE_TYPE_DANCING,
+            EXERCISE_TYPE_ELLIPTICAL,
+            EXERCISE_TYPE_EXERCISE_CLASS,
+            EXERCISE_TYPE_FENCING,
+            EXERCISE_TYPE_FOOTBALL_AMERICAN,
+            EXERCISE_TYPE_FOOTBALL_AUSTRALIAN,
+            EXERCISE_TYPE_FRISBEE_DISC,
+            EXERCISE_TYPE_GOLF,
+            EXERCISE_TYPE_GUIDED_BREATHING,
+            EXERCISE_TYPE_GYMNASTICS,
+            EXERCISE_TYPE_HANDBALL,
+            EXERCISE_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
+            EXERCISE_TYPE_HIKING,
+            EXERCISE_TYPE_ICE_HOCKEY,
+            EXERCISE_TYPE_ICE_SKATING,
+            EXERCISE_TYPE_MARTIAL_ARTS,
+            EXERCISE_TYPE_PADDLING,
+            EXERCISE_TYPE_PARAGLIDING,
+            EXERCISE_TYPE_PILATES,
+            EXERCISE_TYPE_RACQUETBALL,
+            EXERCISE_TYPE_ROCK_CLIMBING,
+            EXERCISE_TYPE_ROLLER_HOCKEY,
+            EXERCISE_TYPE_ROWING,
+            EXERCISE_TYPE_ROWING_MACHINE,
+            EXERCISE_TYPE_RUGBY,
+            EXERCISE_TYPE_RUNNING,
+            EXERCISE_TYPE_RUNNING_TREADMILL,
+            EXERCISE_TYPE_SAILING,
+            EXERCISE_TYPE_SCUBA_DIVING,
+            EXERCISE_TYPE_SKATING,
+            EXERCISE_TYPE_SKIING,
+            EXERCISE_TYPE_SNOWBOARDING,
+            EXERCISE_TYPE_SNOWSHOEING,
+            EXERCISE_TYPE_SOCCER,
+            EXERCISE_TYPE_SOFTBALL,
+            EXERCISE_TYPE_SQUASH,
+            EXERCISE_TYPE_STAIR_CLIMBING,
+            EXERCISE_TYPE_STAIR_CLIMBING_MACHINE,
+            EXERCISE_TYPE_STRENGTH_TRAINING,
+            EXERCISE_TYPE_STRETCHING,
+            EXERCISE_TYPE_SURFING,
+            EXERCISE_TYPE_SWIMMING_OPEN_WATER,
+            EXERCISE_TYPE_SWIMMING_POOL,
+            EXERCISE_TYPE_TABLE_TENNIS,
+            EXERCISE_TYPE_TENNIS,
+            EXERCISE_TYPE_VOLLEYBALL,
+            EXERCISE_TYPE_WALKING,
+            EXERCISE_TYPE_WATER_POLO,
+            EXERCISE_TYPE_WEIGHTLIFTING,
+            EXERCISE_TYPE_WHEELCHAIR,
+            EXERCISE_TYPE_OTHER_WORKOUT,
+            EXERCISE_TYPE_YOGA,
+        ]
     )
     annotation class ExerciseTypes
 }
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseLapTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseLapTest.kt
new file mode 100644
index 0000000..48c7202
--- /dev/null
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseLapTest.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.health.connect.client.records
+
+import androidx.health.connect.client.units.meters
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.time.Instant
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ExerciseLapTest {
+    @Test
+    fun validLap_equals() {
+        assertThat(
+            ExerciseLap(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678L),
+                length = 1.meters
+            )
+        ).isEqualTo(
+            ExerciseLap(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678L),
+                length = 1.meters
+            )
+        )
+    }
+
+    @Test
+    fun invalidTimes_throws() {
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseLap(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(1234L),
+            )
+        }
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseLap(
+                startTime = Instant.ofEpochMilli(5678L),
+                endTime = Instant.ofEpochMilli(1234L),
+            )
+        }
+    }
+
+    @Test
+    fun invalidLength_throws() {
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseLap(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678),
+                length = (-1).meters,
+            )
+        }
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseLap(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678),
+                length = 1_000_001.meters,
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseRouteTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseRouteTest.kt
new file mode 100644
index 0000000..a2edd79
--- /dev/null
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseRouteTest.kt
@@ -0,0 +1,134 @@
+/*
+ * 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.health.connect.client.records
+
+import androidx.health.connect.client.units.Length
+import com.google.common.truth.Truth.assertThat
+import java.time.Instant
+import kotlin.test.assertFailsWith
+import org.junit.Test
+
+class ExerciseRouteTest {
+
+    @Test
+    fun validLocation_equals() {
+        assertThat(
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(1234L),
+                latitude = 34.5,
+                longitude = -34.5,
+                horizontalAccuracy = Length.meters(0.4),
+                verticalAccuracy = Length.meters(1.3),
+                altitude = Length.meters(23.4)
+            )
+        )
+            .isEqualTo(
+                ExerciseRoute.Location(
+                    time = Instant.ofEpochMilli(1234L),
+                    latitude = 34.5,
+                    longitude = -34.5,
+                    horizontalAccuracy = Length.meters(0.4),
+                    verticalAccuracy = Length.meters(1.3),
+                    altitude = Length.meters(23.4)
+                )
+            )
+    }
+
+    @Test
+    fun invalidLatitudeAndLongitude_throws() {
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(1234L),
+                latitude = -91.0,
+                longitude = -34.5,
+                horizontalAccuracy = Length.meters(0.4),
+                verticalAccuracy = Length.meters(1.3),
+                altitude = Length.meters(23.4)
+            )
+        }
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(1234L),
+                latitude = 34.5,
+                longitude = 189.5,
+                horizontalAccuracy = Length.meters(0.4),
+                verticalAccuracy = Length.meters(1.3),
+                altitude = Length.meters(23.4)
+            )
+        }
+    }
+
+    @Test
+    fun emptyRoute() {
+        assertThat(ExerciseRoute(listOf())).isEqualTo(ExerciseRoute(listOf()))
+    }
+
+    @Test
+    fun nonEmptyRoute() {
+        val location1 =
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(1234L),
+                latitude = 34.5,
+                longitude = -34.5,
+                horizontalAccuracy = Length.meters(0.4),
+                verticalAccuracy = Length.meters(1.3),
+                altitude = Length.meters(23.4)
+            )
+        val location2 =
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(2345L),
+                latitude = 34.8,
+                longitude = -34.8,
+            )
+        assertThat(ExerciseRoute(listOf(location1, location2)))
+            .isEqualTo(ExerciseRoute(listOf(location1, location2)))
+    }
+
+    @Test
+    fun locationTimeOverlap_throws() {
+        val location1 = ExerciseRoute.Location(
+            time = Instant.ofEpochMilli(1234L),
+            latitude = 34.5,
+            longitude = -34.5,
+        )
+        val location2 =
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(1234L),
+                latitude = 34.8,
+                longitude = -34.8,
+            )
+        assertFailsWith<IllegalArgumentException> { ExerciseRoute(listOf(location1, location2)) }
+    }
+
+    @Test
+    fun locationTime_sorted() {
+        val location1 = ExerciseRoute.Location(
+            time = Instant.ofEpochMilli(1236L),
+            latitude = 34.5,
+            longitude = -34.5,
+        )
+        val location2 =
+            ExerciseRoute.Location(
+                time = Instant.ofEpochMilli(1235L),
+                latitude = 34.8,
+                longitude = -34.8,
+            )
+        assertThat(ExerciseRoute(listOf(location1, location2)).route).isEqualTo(
+            listOf(location2, location1)
+        )
+    }
+}
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseSegmentTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseSegmentTest.kt
new file mode 100644
index 0000000..b1d35f8
--- /dev/null
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/records/ExerciseSegmentTest.kt
@@ -0,0 +1,284 @@
+/*
+ * 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.health.connect.client.records
+
+import androidx.health.connect.client.records.ExerciseSegment.Companion.EXERCISE_SEGMENTS
+import androidx.health.connect.client.records.ExerciseSegment.Companion.SWIMMING_SEGMENTS
+import androidx.health.connect.client.records.ExerciseSegment.Companion.UNIVERSAL_SEGMENTS
+import androidx.health.connect.client.records.ExerciseSegment.Companion.UNIVERSAL_SESSION_TYPES
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.time.Instant
+import kotlin.reflect.typeOf
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ExerciseSegmentTest {
+    private val allSegmentTypes =
+        ExerciseSegment.Companion::class
+            .members
+            .asSequence()
+            .filter { it.name.startsWith("EXERCISE_SEGMENT_TYPE_") }
+            .filter { it.returnType == typeOf<Int>() }
+            .map { it.call(ExerciseSegment.Companion) as Int }
+            .toSet()
+
+    private val allSessionTypes =
+        ExerciseSessionRecord.Companion::class
+            .members
+            .asSequence()
+            .filter { it.name.startsWith("EXERCISE_TYPE_") }
+            .filter { it.returnType == typeOf<Int>() }
+            .map { it.call(ExerciseSegment.Companion) as Int }
+            .toSet()
+
+    private val exerciseSessionTypes = setOf(
+        ExerciseSessionRecord.EXERCISE_TYPE_CALISTHENICS,
+        ExerciseSessionRecord.EXERCISE_TYPE_GYMNASTICS,
+        ExerciseSessionRecord.EXERCISE_TYPE_STRENGTH_TRAINING,
+        ExerciseSessionRecord.EXERCISE_TYPE_WEIGHTLIFTING
+    )
+
+    private val swimmingSessionTypes = setOf(
+        ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_POOL,
+        ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_OPEN_WATER,
+    )
+
+    private val hikingSegments = setOf(
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_WALKING,
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_WHEELCHAIR
+    )
+
+    private val runningSegments = setOf(
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING,
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_WALKING
+    )
+
+    private val exerciseClassSegments = setOf(
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY,
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_PILATES,
+        ExerciseSegment.EXERCISE_SEGMENT_TYPE_YOGA,
+    )
+
+    private val sameSessionAndSegmentTypePairs = mapOf(
+        ExerciseSessionRecord.EXERCISE_TYPE_BIKING to ExerciseSegment.EXERCISE_SEGMENT_TYPE_BIKING,
+        ExerciseSessionRecord.EXERCISE_TYPE_BIKING_STATIONARY
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY,
+        ExerciseSessionRecord.EXERCISE_TYPE_ELLIPTICAL
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_ELLIPTICAL,
+        ExerciseSessionRecord.EXERCISE_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
+        ExerciseSessionRecord.EXERCISE_TYPE_PILATES
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_PILATES,
+        ExerciseSessionRecord.EXERCISE_TYPE_ROWING_MACHINE
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_ROWING_MACHINE,
+        ExerciseSessionRecord.EXERCISE_TYPE_RUNNING
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING,
+        ExerciseSessionRecord.EXERCISE_TYPE_RUNNING_TREADMILL
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL,
+        ExerciseSessionRecord.EXERCISE_TYPE_STAIR_CLIMBING
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING,
+        ExerciseSessionRecord.EXERCISE_TYPE_STAIR_CLIMBING_MACHINE
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE,
+        ExerciseSessionRecord.EXERCISE_TYPE_STRETCHING
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_STRETCHING,
+        ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_OPEN_WATER
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_SWIMMING_OPEN_WATER,
+        ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_POOL
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_SWIMMING_POOL,
+        ExerciseSessionRecord.EXERCISE_TYPE_WALKING
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_WALKING,
+        ExerciseSessionRecord.EXERCISE_TYPE_WEIGHTLIFTING
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_WEIGHTLIFTING,
+        ExerciseSessionRecord.EXERCISE_TYPE_WHEELCHAIR
+            to ExerciseSegment.EXERCISE_SEGMENT_TYPE_WHEELCHAIR,
+        ExerciseSessionRecord.EXERCISE_TYPE_YOGA to ExerciseSegment.EXERCISE_SEGMENT_TYPE_YOGA,
+    )
+
+    @Test
+    fun validSegment_equals() {
+        assertThat(
+            ExerciseSegment(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678L),
+                segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_PLANK,
+                repetitions = 10,
+            )
+        ).isEqualTo(
+            ExerciseSegment(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678L),
+                segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_PLANK,
+                repetitions = 10,
+            )
+        )
+    }
+
+    @Test
+    fun invalidTimes_throws() {
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseSegment(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(1234L),
+                segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_PLANK,
+            )
+        }
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseSegment(
+                startTime = Instant.ofEpochMilli(5678L),
+                endTime = Instant.ofEpochMilli(1234L),
+                segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_PLANK,
+            )
+        }
+    }
+
+    @Test
+    fun invalidReps_throws() {
+        assertFailsWith<IllegalArgumentException> {
+            ExerciseSegment(
+                startTime = Instant.ofEpochMilli(1234L),
+                endTime = Instant.ofEpochMilli(5678),
+                segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_PLANK,
+                repetitions = -1,
+            )
+        }
+    }
+
+    @Test
+    fun isCompatible_universalSession_acceptsEverything() {
+        UNIVERSAL_SESSION_TYPES.forEach { sessionType ->
+            allSegmentTypes.forEach { segmentType ->
+                assertCompatibility(sessionType, segmentType)
+            }
+        }
+    }
+
+    @Test
+    fun isCompatible_universalSegment_fitsInEverything() {
+        allSessionTypes.forEach { sessionType ->
+            UNIVERSAL_SEGMENTS.forEach { segmentType ->
+                assertCompatibility(sessionType, segmentType)
+            }
+        }
+    }
+
+    @Test
+    fun isCompatible_sameSessionAndSegmentType_returnsTrue() {
+        sameSessionAndSegmentTypePairs.forEach { (sessionType, segmentType) ->
+            assertCompatibility(sessionType, segmentType)
+        }
+    }
+
+    @Test
+    fun isCompatible_genericExerciseSessions_acceptGenericExerciseSegments() {
+        exerciseSessionTypes.forEach { sessionType ->
+            EXERCISE_SEGMENTS.forEach { segmentType ->
+                assertCompatibility(sessionType, segmentType)
+            }
+        }
+    }
+
+    @Test
+    fun isCompatible_swimmingSessions_acceptSwimmingSegments() {
+        swimmingSessionTypes.forEach { sessionType ->
+            SWIMMING_SEGMENTS.forEach { segmentType ->
+                assertCompatibility(sessionType, segmentType)
+            }
+        }
+    }
+
+    @Test
+    fun isCompatible_exerciseClassSession_acceptClassSegments() {
+        assertCompatibility(
+            ExerciseSessionRecord.EXERCISE_TYPE_EXERCISE_CLASS,
+            ExerciseSegment.EXERCISE_SEGMENT_TYPE_YOGA
+        )
+        assertCompatibility(
+            ExerciseSessionRecord.EXERCISE_TYPE_EXERCISE_CLASS,
+            ExerciseSegment.EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY
+        )
+        assertCompatibility(
+            ExerciseSessionRecord.EXERCISE_TYPE_EXERCISE_CLASS,
+            ExerciseSegment.EXERCISE_SEGMENT_TYPE_PILATES
+        )
+        assertCompatibility(
+            ExerciseSessionRecord.EXERCISE_TYPE_EXERCISE_CLASS,
+            ExerciseSegment.EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING
+        )
+    }
+
+    @Test
+    fun isCompatible_hikingSession_acceptWalkingAndWheelchair() {
+        hikingSegments.forEach { segmentType ->
+            assertCompatibility(ExerciseSessionRecord.EXERCISE_TYPE_HIKING, segmentType)
+        }
+    }
+
+    @Test
+    fun isCompatible_runningSession_acceptRunningAndWalking() {
+        runningSegments.forEach { segmentType ->
+            assertCompatibility(ExerciseSessionRecord.EXERCISE_TYPE_RUNNING, segmentType)
+        }
+    }
+
+    @Test
+    fun isCompatible_allOtherCombinations_returnsFalse() {
+        allSessionTypes.filter { !UNIVERSAL_SESSION_TYPES.contains(it) }.forEach { sessionType ->
+            allSegmentTypes.asSequence().filter { !UNIVERSAL_SEGMENTS.contains(it) }
+                .filter { !(sameSessionAndSegmentTypePairs[sessionType]?.equals(it) ?: false) }
+                .filter {
+                    !(exerciseSessionTypes.contains(sessionType) && EXERCISE_SEGMENTS.contains(it))
+                }
+                .filter {
+                    !(swimmingSessionTypes.contains(sessionType) && SWIMMING_SEGMENTS.contains(it))
+                }
+                .filter {
+                    !(sessionType == ExerciseSessionRecord.EXERCISE_TYPE_EXERCISE_CLASS &&
+                        exerciseClassSegments.contains(it))
+                }
+                .filter {
+                    !(sessionType == ExerciseSessionRecord.EXERCISE_TYPE_HIKING &&
+                        hikingSegments.contains(it))
+                }
+                .filter {
+                    !(sessionType == ExerciseSessionRecord.EXERCISE_TYPE_RUNNING &&
+                        runningSegments.contains(it))
+                }.toList()
+                .forEach { segmentType -> assertCompatibility(sessionType, segmentType, false) }
+        }
+    }
+
+    private fun assertCompatibility(
+        sessionType: Int,
+        segmentType: Int,
+        isCompatible: Boolean = true
+    ) {
+        assertEquals(
+            expected = isCompatible,
+            actual = ExerciseSegment(
+                startTime = Instant.ofEpochMilli(1),
+                endTime = Instant.ofEpochMilli(2),
+                segmentType = segmentType
+            ).isCompatibleWith(sessionType),
+            message = "$sessionType and $segmentType is not compatible"
+        )
+    }
+}
\ No newline at end of file
diff --git a/javascriptengine/javascriptengine/api/aidlRelease/current/org/chromium/android_webview/js_sandbox/common/IJsSandboxConsoleCallback.aidl b/javascriptengine/javascriptengine/api/aidlRelease/current/org/chromium/android_webview/js_sandbox/common/IJsSandboxConsoleCallback.aidl
index f7888a7..96b70225 100644
--- a/javascriptengine/javascriptengine/api/aidlRelease/current/org/chromium/android_webview/js_sandbox/common/IJsSandboxConsoleCallback.aidl
+++ b/javascriptengine/javascriptengine/api/aidlRelease/current/org/chromium/android_webview/js_sandbox/common/IJsSandboxConsoleCallback.aidl
@@ -36,9 +36,9 @@
 interface IJsSandboxConsoleCallback {
   void consoleMessage(int contextGroupId, int level, String message, String source, int line, int column, String trace) = 0;
   void consoleClear(int contextGroupId) = 1;
-  const int CONSOLE_MESSAGE_LEVEL_LOG = (1 << 0);
-  const int CONSOLE_MESSAGE_LEVEL_DEBUG = (1 << 1);
-  const int CONSOLE_MESSAGE_LEVEL_INFO = (1 << 2);
-  const int CONSOLE_MESSAGE_LEVEL_ERROR = (1 << 3);
-  const int CONSOLE_MESSAGE_LEVEL_WARNING = (1 << 4);
+  const int CONSOLE_MESSAGE_LEVEL_LOG = (1 << 0) /* 1 */;
+  const int CONSOLE_MESSAGE_LEVEL_DEBUG = (1 << 1) /* 2 */;
+  const int CONSOLE_MESSAGE_LEVEL_INFO = (1 << 2) /* 4 */;
+  const int CONSOLE_MESSAGE_LEVEL_ERROR = (1 << 3) /* 8 */;
+  const int CONSOLE_MESSAGE_LEVEL_WARNING = (1 << 4) /* 16 */;
 }
diff --git a/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java b/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
index 553e919..8a7e238 100644
--- a/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
+++ b/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 
 import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
@@ -957,7 +958,8 @@
             }
 
             @Override
-            public void onConsoleMessage(JavaScriptConsoleCallback.ConsoleMessage message) {
+            public void onConsoleMessage(
+                    @NonNull JavaScriptConsoleCallback.ConsoleMessage message) {
                 synchronized (mLock) {
                     mMessages.append(message.toString()).append("\n");
                 }
@@ -1123,7 +1125,7 @@
             CountDownLatch latch = new CountDownLatch(1);
             jsIsolate.setConsoleCallback(new JavaScriptConsoleCallback() {
                 @Override
-                public void onConsoleMessage(ConsoleMessage message) {}
+                public void onConsoleMessage(@NonNull ConsoleMessage message) {}
 
                 @Override
                 public void onConsoleClear() {
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptConsoleCallback.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptConsoleCallback.java
index 75ed67b..b7acd25 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptConsoleCallback.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptConsoleCallback.java
@@ -162,6 +162,7 @@
             return mTrace;
         }
 
+        @NonNull
         @Override
         public String toString() {
             return new StringBuilder()
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java
index f1a563b..00afeb8 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java
@@ -37,6 +37,7 @@
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -89,15 +90,17 @@
 
     private class IJsSandboxIsolateSyncCallbackStubWrapper extends
             IJsSandboxIsolateSyncCallback.Stub {
+        @NonNull
         private CallbackToFutureAdapter.Completer<String> mCompleter;
 
         IJsSandboxIsolateSyncCallbackStubWrapper(
-                CallbackToFutureAdapter.Completer<String> completer) {
+                @NonNull CallbackToFutureAdapter.Completer<String> completer) {
             mCompleter = completer;
         }
 
         @Override
         public void reportResultWithFd(AssetFileDescriptor afd) {
+            Objects.requireNonNull(afd);
             mJsSandbox.mThreadPoolTaskExecutor.execute(
                     () -> {
                         String result;
@@ -128,6 +131,7 @@
 
         @Override
         public void reportErrorWithFd(@ExecutionErrorTypes int type, AssetFileDescriptor afd) {
+            Objects.requireNonNull(afd);
             mJsSandbox.mThreadPoolTaskExecutor.execute(
                     () -> {
                         String error;
@@ -147,29 +151,36 @@
     }
 
     private class IJsSandboxIsolateCallbackStubWrapper extends IJsSandboxIsolateCallback.Stub {
+        @NonNull
         private CallbackToFutureAdapter.Completer<String> mCompleter;
 
-        IJsSandboxIsolateCallbackStubWrapper(CallbackToFutureAdapter.Completer<String> completer) {
+        IJsSandboxIsolateCallbackStubWrapper(
+                @NonNull CallbackToFutureAdapter.Completer<String> completer) {
             mCompleter = completer;
         }
 
         @Override
         public void reportResult(String result) {
+            Objects.requireNonNull(result);
             handleEvaluationResult(mCompleter, result);
         }
 
         @Override
         public void reportError(@ExecutionErrorTypes int type, String error) {
+            Objects.requireNonNull(error);
             handleEvaluationError(mCompleter, type, error);
         }
     }
 
     private static final class JsSandboxConsoleCallbackRelay
             extends IJsSandboxConsoleCallback.Stub {
+        @NonNull
         private final Executor mExecutor;
+        @NonNull
         private final JavaScriptConsoleCallback mCallback;
 
-        JsSandboxConsoleCallbackRelay(Executor executor, JavaScriptConsoleCallback callback) {
+        JsSandboxConsoleCallbackRelay(@NonNull Executor executor,
+                @NonNull JavaScriptConsoleCallback callback) {
             mExecutor = executor;
             mCallback = callback;
         }
@@ -185,12 +196,8 @@
                         throw new IllegalArgumentException(
                                 "invalid console level " + level + " provided by isolate");
                     }
-                    if (message == null) {
-                        throw new IllegalArgumentException("null message provided by isolate");
-                    }
-                    if (source == null) {
-                        throw new IllegalArgumentException("null source provided by isolate");
-                    }
+                    Objects.requireNonNull(message);
+                    Objects.requireNonNull(source);
                     mCallback.onConsoleMessage(
                             new JavaScriptConsoleCallback.ConsoleMessage(
                                 level, message, source, line, column, trace));
@@ -215,8 +222,8 @@
         }
     }
 
-    JavaScriptIsolate(IJsSandboxIsolate jsIsolateStub, JavaScriptSandbox sandbox,
-            IsolateStartupParameters settings) {
+    JavaScriptIsolate(@NonNull IJsSandboxIsolate jsIsolateStub, @NonNull JavaScriptSandbox sandbox,
+            @NonNull IsolateStartupParameters settings) {
         mJsSandbox = sandbox;
         mJsIsolateStub = jsIsolateStub;
         mStartupParameters = settings;
@@ -266,6 +273,7 @@
     @SuppressWarnings("NullAway")
     @NonNull
     public ListenableFuture<String> evaluateJavaScriptAsync(@NonNull String code) {
+        Objects.requireNonNull(code);
         if (!mSandboxClosed.get() && mJsSandbox.isFeatureSupported(
                 JavaScriptSandbox.JS_FEATURE_EVALUATE_WITHOUT_TRANSACTION_LIMIT)) {
             // This process can be made more memory efficient by converting the String to
@@ -324,6 +332,7 @@
     @RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_EVALUATE_WITHOUT_TRANSACTION_LIMIT,
             enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
     public ListenableFuture<String> evaluateJavaScriptAsync(@NonNull byte[] code) {
+        Objects.requireNonNull(code);
         if (mJsIsolateStub == null) {
             throw new IllegalStateException(
                     "Calling evaluateJavaScriptAsync() after closing the Isolate");
@@ -441,12 +450,11 @@
     @RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER,
             enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
     public boolean provideNamedData(@NonNull String name, @NonNull byte[] inputBytes) {
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(inputBytes);
         if (mJsIsolateStub == null) {
             throw new IllegalStateException("Calling provideNamedData() after closing the Isolate");
         }
-        if (name == null) {
-            throw new NullPointerException("name parameter cannot be null");
-        }
         try {
             AssetFileDescriptor codeAfd = Utils.writeBytesIntoPipeAsync(inputBytes,
                     mJsSandbox.mThreadPoolTaskExecutor);
@@ -465,8 +473,8 @@
         return false;
     }
 
-    void handleEvaluationError(CallbackToFutureAdapter.Completer<String> completer,
-            int type, String error) {
+    void handleEvaluationError(@NonNull CallbackToFutureAdapter.Completer<String> completer,
+            int type, @NonNull String error) {
         boolean crashing = false;
         switch (type) {
             case IJsSandboxIsolateSyncCallback.JS_EVALUATION_ERROR:
@@ -488,8 +496,8 @@
         }
     }
 
-    void handleEvaluationResult(CallbackToFutureAdapter.Completer<String> completer,
-            String result) {
+    void handleEvaluationResult(@NonNull CallbackToFutureAdapter.Completer<String> completer,
+            @NonNull String result) {
         completer.set(result);
         removePending(completer);
     }
@@ -501,7 +509,7 @@
 
     // Cancel all pending and future evaluations with the given exception.
     // Only the first call to this method has any effect.
-    void cancelAllPendingEvaluations(Exception e) {
+    void cancelAllPendingEvaluations(@NonNull Exception e) {
         final HashSet<CallbackToFutureAdapter.Completer<String>> pendingSet;
         synchronized (mSetLock) {
             if (mPendingCompleterSet == null) return;
@@ -514,7 +522,7 @@
         }
     }
 
-    void removePending(CallbackToFutureAdapter.Completer<String> completer) {
+    void removePending(@NonNull CallbackToFutureAdapter.Completer<String> completer) {
         synchronized (mSetLock) {
             if (mPendingCompleterSet != null) {
                 mPendingCompleterSet.remove(completer);
@@ -568,12 +576,8 @@
             enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
     public void setConsoleCallback(@NonNull Executor executor,
             @NonNull JavaScriptConsoleCallback callback) {
-        if (executor == null) {
-            throw new IllegalArgumentException("executor cannot be null");
-        }
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null");
-        }
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
         if (mJsIsolateStub == null) {
             throw new IllegalStateException(
                     "Calling setConsoleCallback() after closing the Isolate");
@@ -597,6 +601,7 @@
     @RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_CONSOLE_MESSAGING,
             enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
     public void setConsoleCallback(@NonNull JavaScriptConsoleCallback callback) {
+        Objects.requireNonNull(callback);
         setConsoleCallback(mJsSandbox.getMainExecutor(), callback);
     }
 
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java
index d98ab90..f7541ce 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java
@@ -45,6 +45,7 @@
 import java.lang.annotation.Target;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -248,7 +249,7 @@
                     new RuntimeException("JavaScriptSandbox internal error: onNullBinding()"));
         }
 
-        private void runShutdownTasks(Exception e) {
+        private void runShutdownTasks(@NonNull Exception e) {
             if (mJsSandbox != null) {
                 mJsSandbox.close();
             } else {
@@ -261,7 +262,7 @@
             mCompleter = null;
         }
 
-        ConnectionSetup(Context context,
+        ConnectionSetup(@NonNull Context context,
                 @NonNull CallbackToFutureAdapter.Completer<JavaScriptSandbox> completer) {
             mContext = context;
             mCompleter = completer;
@@ -286,6 +287,7 @@
     @NonNull
     public static ListenableFuture<JavaScriptSandbox> createConnectedInstanceAsync(
             @NonNull Context context) {
+        Objects.requireNonNull(context);
         if (!isSupported()) {
             throw new SandboxUnsupportedException("The system does not support JavaScriptSandbox");
         }
@@ -313,6 +315,7 @@
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static ListenableFuture<JavaScriptSandbox> createConnectedInstanceForTestingAsync(
             @NonNull Context context) {
+        Objects.requireNonNull(context);
         ComponentName compName = new ComponentName(context, JS_SANDBOX_SERVICE_NAME);
         int flag = Context.BIND_AUTO_CREATE;
         return bindToServiceWithCallback(context, compName, flag);
@@ -326,7 +329,6 @@
      *
      * @return true if JavaScriptSandbox is supported and false otherwise.
      */
-    @NonNull
     public static boolean isSupported() {
         PackageInfo systemWebViewPackage = WebView.getCurrentWebViewPackage();
         if (systemWebViewPackage == null) {
@@ -343,7 +345,7 @@
 
     @NonNull
     private static ListenableFuture<JavaScriptSandbox> bindToServiceWithCallback(
-            Context context, ComponentName compName, int flag) {
+            @NonNull Context context, @NonNull ComponentName compName, int flag) {
         Intent intent = new Intent();
         intent.setComponent(compName);
         return CallbackToFutureAdapter.getFuture(completer -> {
@@ -381,7 +383,8 @@
 
     // We prevent direct initializations of this class.
     // Use JavaScriptSandbox.createConnectedInstance().
-    JavaScriptSandbox(ConnectionSetup connectionSetup, IJsSandboxService jsSandboxService) {
+    JavaScriptSandbox(@NonNull ConnectionSetup connectionSetup,
+            @NonNull IJsSandboxService jsSandboxService) {
         mConnection = connectionSetup;
         synchronized (mLock) {
             mJsSandboxService = jsSandboxService;
@@ -407,6 +410,7 @@
      */
     @NonNull
     public JavaScriptIsolate createIsolate(@NonNull IsolateStartupParameters settings) {
+        Objects.requireNonNull(settings);
         synchronized (mLock) {
             if (mJsSandboxService == null) {
                 throw new IllegalStateException(
@@ -462,9 +466,10 @@
     }
 
     @GuardedBy("mLock")
+    @NonNull
     @SuppressWarnings("NullAway")
-    private JavaScriptIsolate createJsIsolateLocked(IJsSandboxIsolate isolateStub,
-            IsolateStartupParameters settings) {
+    private JavaScriptIsolate createJsIsolateLocked(@NonNull IJsSandboxIsolate isolateStub,
+            @NonNull IsolateStartupParameters settings) {
         JavaScriptIsolate isolate = new JavaScriptIsolate(isolateStub, this, settings);
         mActiveIsolateSet.add(isolate);
         return isolate;
@@ -483,7 +488,8 @@
      * @return {@code true} if supported, {@code false} otherwise
      */
     @SuppressWarnings("NullAway")
-    public boolean isFeatureSupported(@NonNull @JsSandboxFeature String feature) {
+    public boolean isFeatureSupported(@JsSandboxFeature @NonNull String feature) {
+        Objects.requireNonNull(feature);
         synchronized (mLock) {
             if (mJsSandboxService == null) {
                 throw new IllegalStateException(
@@ -496,7 +502,7 @@
         }
     }
 
-    void removeFromIsolateSet(JavaScriptIsolate isolate) {
+    void removeFromIsolateSet(@NonNull JavaScriptIsolate isolate) {
         synchronized (mLock) {
             if (mActiveIsolateSet != null) {
                 mActiveIsolateSet.remove(isolate);
@@ -562,6 +568,7 @@
         }
     }
 
+    @NonNull
     Executor getMainExecutor() {
         return ContextCompat.getMainExecutor(mConnection.mContext);
     }
diff --git a/libraryversions.toml b/libraryversions.toml
index ec838a5..c511569 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -14,12 +14,12 @@
 BLUETOOTH = "1.0.0-alpha01"
 BROWSER = "1.6.0-alpha01"
 BUILDSRC_TESTS = "1.0.0-alpha01"
-CAMERA = "1.3.0-alpha06"
+CAMERA = "1.3.0-alpha07"
 CAMERA_PIPE = "1.0.0-alpha01"
 CARDVIEW = "1.1.0-alpha01"
 CAR_APP = "1.4.0-alpha01"
 COLLECTION = "1.3.0-alpha05"
-COMPOSE = "1.5.0-alpha03"
+COMPOSE = "1.5.0-alpha04"
 COMPOSE_COMPILER = "1.4.6"
 COMPOSE_MATERIAL3 = "1.2.0-alpha01"
 COMPOSE_MATERIAL3_ADAPTIVE = "1.0.0-alpha01"
@@ -29,7 +29,7 @@
 CONSTRAINTLAYOUT_CORE = "1.1.0-alpha10"
 CONTENTPAGER = "1.1.0-alpha01"
 COORDINATORLAYOUT = "1.3.0-alpha01"
-CORE = "1.11.0-alpha03"
+CORE = "1.11.0-alpha04"
 CORE_ANIMATION = "1.0.0-beta02"
 CORE_ANIMATION_TESTING = "1.0.0-beta01"
 CORE_APPDIGEST = "1.0.0-alpha01"
@@ -41,7 +41,7 @@
 CORE_ROLE = "1.2.0-alpha01"
 CORE_SPLASHSCREEN = "1.1.0-alpha01"
 CORE_UWB = "1.0.0-alpha06"
-CREDENTIALS = "1.0.0-alpha07"
+CREDENTIALS = "1.0.0-alpha08"
 CURSORADAPTER = "1.1.0-alpha01"
 CUSTOMVIEW = "1.2.0-alpha03"
 CUSTOMVIEW_POOLINGCONTAINER = "1.1.0-alpha01"
@@ -52,21 +52,23 @@
 DYNAMICANIMATION = "1.1.0-alpha04"
 DYNAMICANIMATION_KTX = "1.0.0-alpha04"
 EMOJI = "1.2.0-alpha03"
-EMOJI2 = "1.4.0-beta02"
+EMOJI2 = "1.4.0-beta03"
 ENTERPRISE = "1.1.0-rc01"
 EXIFINTERFACE = "1.4.0-alpha01"
-FRAGMENT = "1.6.0-beta01"
+FRAGMENT = "1.6.0-rc01"
 FUTURES = "1.2.0-alpha01"
-GLANCE = "1.0.0-alpha06"
-GLANCE_TEMPLATE = "1.0.0-alpha01"
+GLANCE = "1.0.0-beta01"
+GLANCE_PREVIEW = "1.0.0-alpha06"
+GLANCE_TEMPLATE = "1.0.0-alpha06"
+GLANCE_WEAR_TILES = "1.0.0-alpha06"
 GRAPHICS_CORE = "1.0.0-alpha04"
 GRAPHICS_FILTERS = "1.0.0-alpha01"
-GRAPHICS_SHAPES = "1.0.0-alpha02"
+GRAPHICS_SHAPES = "1.0.0-alpha03"
 GRIDLAYOUT = "1.1.0-alpha02"
 HEALTH_CONNECT = "1.0.0-alpha11"
 HEALTH_SERVICES_CLIENT = "1.0.0-beta04"
 HEIFWRITER = "1.1.0-alpha02"
-HILT = "1.1.0-alpha02"
+HILT = "1.1.0-alpha03"
 HILT_NAVIGATION_COMPOSE = "1.1.0-alpha02"
 INPUT_MOTIONPREDICTION = "1.0.0-beta02"
 INSPECTION = "1.0.0"
@@ -86,18 +88,18 @@
 MEDIA2 = "1.3.0-alpha01"
 MEDIAROUTER = "1.5.0-alpha01"
 METRICS = "1.0.0-alpha05"
-NAVIGATION = "2.6.0-beta01"
+NAVIGATION = "2.6.0-rc01"
 PAGING = "3.2.0-alpha05"
 PAGING_COMPOSE = "1.0.0-alpha19"
 PALETTE = "1.1.0-alpha01"
 PERCENTLAYOUT = "1.1.0-alpha01"
 PREFERENCE = "1.3.0-alpha01"
 PRINT = "1.1.0-beta01"
-PRIVACYSANDBOX_ADS = "1.0.0-beta03"
+PRIVACYSANDBOX_ADS = "1.0.0-beta04"
 PRIVACYSANDBOX_PLUGINS = "1.0.0-alpha02"
 PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha04"
 PRIVACYSANDBOX_TOOLS = "1.0.0-alpha04"
-PRIVACYSANDBOX_UI = "1.0.0-alpha02"
+PRIVACYSANDBOX_UI = "1.0.0-alpha03"
 PROFILEINSTALLER = "1.4.0-alpha01"
 RECOMMENDATION = "1.1.0-alpha01"
 RECYCLERVIEW = "1.4.0-alpha01"
@@ -106,7 +108,7 @@
 RESOURCEINSPECTION = "1.1.0-alpha01"
 ROOM = "2.6.0-alpha02"
 SAVEDSTATE = "1.3.0-alpha01"
-SECURITY = "1.1.0-alpha06"
+SECURITY = "1.1.0-alpha07"
 SECURITY_APP_AUTHENTICATOR = "1.0.0-alpha03"
 SECURITY_APP_AUTHENTICATOR_TESTING = "1.0.0-alpha02"
 SECURITY_BIOMETRIC = "1.0.0-alpha01"
@@ -124,7 +126,7 @@
 SWIPEREFRESHLAYOUT = "1.2.0-alpha01"
 TESTEXT = "1.0.0-alpha02"
 TESTSCREENSHOT = "1.0.0-alpha01"
-TEST_UIAUTOMATOR = "2.3.0-alpha03"
+TEST_UIAUTOMATOR = "2.3.0-alpha04"
 TEXT = "1.0.0-alpha01"
 TRACING = "1.2.0-beta04"
 TRACING_PERFETTO = "1.0.0-alpha15"
@@ -137,17 +139,17 @@
 VERSIONED_PARCELABLE = "1.2.0-alpha01"
 VIEWPAGER = "1.1.0-alpha02"
 VIEWPAGER2 = "1.2.0-alpha01"
-WEAR = "1.3.0-alpha05"
-WEAR_COMPOSE = "1.2.0-alpha09"
-WEAR_COMPOSE_MATERIAL3 = "1.0.0-alpha03"
+WEAR = "1.3.0-alpha06"
+WEAR_COMPOSE = "1.2.0-alpha10"
+WEAR_COMPOSE_MATERIAL3 = "1.0.0-alpha04"
 WEAR_INPUT = "1.2.0-alpha03"
 WEAR_INPUT_TESTING = "1.2.0-alpha03"
 WEAR_ONGOING = "1.1.0-alpha01"
 WEAR_PHONE_INTERACTIONS = "1.1.0-alpha04"
-WEAR_PROTOLAYOUT = "1.0.0-alpha08"
+WEAR_PROTOLAYOUT = "1.0.0-alpha09"
 WEAR_REMOTE_INTERACTIONS = "1.1.0-alpha01"
-WEAR_TILES = "1.2.0-alpha04"
-WEAR_WATCHFACE = "1.2.0-alpha08"
+WEAR_TILES = "1.2.0-alpha05"
+WEAR_WATCHFACE = "1.2.0-alpha09"
 WEBKIT = "1.8.0-alpha01"
 WINDOW = "1.2.0-alpha01"
 WINDOW_EXTENSIONS = "1.2.0-alpha01"
@@ -204,7 +206,6 @@
 EXIFINTERFACE = { group = "androidx.exifinterface", atomicGroupVersion = "versions.EXIFINTERFACE" }
 FRAGMENT = { group = "androidx.fragment", atomicGroupVersion = "versions.FRAGMENT" }
 GLANCE = { group = "androidx.glance", atomicGroupVersion = "versions.GLANCE" }
-GLANCE_TEMPLATE = { group = "androidx.template", atomicGroupVersion = "versions.GLANCE_TEMPLATE" }
 GRAPHICS = { group = "androidx.graphics" }
 GRAPHICS_FILTERS = { group = "androidx.graphics.filters", atomicGroupVersion = "versions.GRAPHICS_FILTERS" }
 GRIDLAYOUT = { group = "androidx.gridlayout", atomicGroupVersion = "versions.GRIDLAYOUT" }
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
index 6482e0a..a7a8099 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
@@ -34,6 +34,7 @@
 import com.intellij.psi.impl.source.PsiImmediateClassType
 import org.jetbrains.kotlin.asJava.elements.KtLightTypeParameter
 import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtCallableDeclaration
 import org.jetbrains.kotlin.psi.KtNullableType
 import org.jetbrains.kotlin.psi.KtTypeReference
 import org.jetbrains.uast.UAnnotated
@@ -46,6 +47,7 @@
 import org.jetbrains.uast.kotlin.KotlinUField
 import org.jetbrains.uast.kotlin.KotlinUSimpleReferenceExpression
 import org.jetbrains.uast.resolveToUElement
+import org.jetbrains.uast.toUElement
 
 /**
  * Lint check for ensuring that [androidx.lifecycle.MutableLiveData] values are never null when
@@ -211,7 +213,7 @@
                     "Cannot set non-nullable LiveData value to `null`",
                     fixes
                 )
-            } else if (argument.isNullable()) {
+            } else if (argument.isNullable(context)) {
                 fixes.add(
                     fix().name("Add non-null asserted (!!) call")
                         .replace().with("!!").range(context.getLocation(argument)).end().build()
@@ -258,10 +260,17 @@
  *
  * @return `true` if instance is nullable, `false` otherwise.
  */
-internal fun UElement.isNullable(): Boolean {
+internal fun UElement.isNullable(context: JavaContext): Boolean {
     if (this is UCallExpression) {
         val psiMethod = resolve() ?: return false
-        return psiMethod.hasAnnotation(NULLABLE_ANNOTATION)
+        val sourceMethod = psiMethod.toUElement()?.sourcePsi
+        if (sourceMethod is KtCallableDeclaration) {
+            // if we have source, check the suspend return type
+            return sourceMethod.typeReference?.typeElement is KtNullableType
+        }
+        // Suspend functions have @Nullable Object return type in JVM
+        val isSuspendMethod = !context.evaluator.isSuspend(psiMethod)
+        return psiMethod.hasAnnotation(NULLABLE_ANNOTATION) && isSuspendMethod
     } else if (this is UReferenceExpression) {
         return (resolveToUElement() as? UAnnotated)?.findAnnotation(NULLABLE_ANNOTATION) != null
     }
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
index b6c0412..97e2074 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
@@ -23,6 +23,7 @@
 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
 import com.android.tools.lint.checks.infrastructure.TestFile
 import com.android.tools.lint.checks.infrastructure.TestLintResult
+import com.android.tools.lint.checks.infrastructure.TestMode
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Ignore
@@ -38,7 +39,7 @@
         mutableListOf(NonNullableMutableLiveDataDetector.ISSUE)
 
     private fun check(vararg files: TestFile): TestLintResult {
-        return lint().files(*files, *STUBS)
+        return lint().files(*files, *STUBS).testModes(TestMode.DEFAULT)
             .run()
     }
 
@@ -101,7 +102,6 @@
         ).expectClean()
     }
 
-    @Ignore("b/196832482")
     @Test
     fun helperMethodFails() {
         check(
@@ -132,7 +132,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun variableAssignmentFails() {
         check(
@@ -170,7 +169,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nullLiteralFailField() {
         check(
@@ -197,7 +195,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nullLiteralFailMultipleFields() {
         check(
@@ -255,7 +252,6 @@
         ).expectClean()
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nullLiteralFailMultipleAssignment() {
         check(
@@ -283,7 +279,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nullLiteralFailFieldAndIgnore() {
         check(
@@ -356,7 +351,6 @@
         ).expectClean()
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nullLiteralFailFieldAndLocalVariable() {
         check(
@@ -388,7 +382,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nullLiteralQuickFix() {
         check(
@@ -414,7 +407,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun classHierarchyTest() {
         check(
@@ -457,7 +449,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun differentClassSameFieldTestFirstNull() {
         check(
@@ -508,7 +499,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun differentClassSameFieldTestSecondNull() {
         check(
@@ -559,7 +549,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun nestedClassSameFieldTest() {
         check(
@@ -603,7 +592,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun modifiersFieldTest() {
         check(
@@ -644,7 +632,6 @@
         )
     }
 
-    @Ignore("b/196832482")
     @Test
     fun implementationClassTest() {
         check(
@@ -820,4 +807,49 @@
             ).indented()
         ).expectClean()
     }
+
+    @Test
+    fun suspendFunction() {
+        check(kotlin("""
+            package com.example
+
+            import androidx.lifecycle.MutableLiveData
+
+            class Foo(
+                var target: MutableLiveData<Boolean>
+            ) {
+
+                suspend fun foo() {
+                    target.value = nonNullable()
+                }
+
+                suspend fun nonNullable() = true
+            }
+        """).indented()).expectClean()
+    }
+
+    @Test
+    fun nullableSuspendFunction() {
+        check(kotlin("""
+            package com.example
+
+            import androidx.lifecycle.MutableLiveData
+
+            class Foo(
+                var target: MutableLiveData<String>
+            ) {
+
+                suspend fun foo() {
+                    target.value = nullable()
+                }
+
+                suspend fun nullable(): String? = null
+            }
+        """).indented()).expect("""
+src/com/example/Foo.kt:10: Error: Expected non-nullable value [NullSafeMutableLiveData]
+        target.value = nullable()
+                       ~~~~~~~~~~
+1 errors, 0 warnings
+        """)
+    }
 }
diff --git a/lifecycle/lifecycle-runtime/proguard-rules.pro b/lifecycle/lifecycle-runtime/proguard-rules.pro
index e4b2c95..95192c1 100644
--- a/lifecycle/lifecycle-runtime/proguard-rules.pro
+++ b/lifecycle/lifecycle-runtime/proguard-rules.pro
@@ -7,9 +7,6 @@
     <fields>;
 }
 
--keep !interface * implements androidx.lifecycle.LifecycleObserver {
-}
-
 -keep class * implements androidx.lifecycle.GeneratedAdapter {
     <init>(...);
 }
diff --git a/lint-checks/integration-tests/src/main/java/androidx/RestrictToTestsAnnotationUsageJava.java b/lint-checks/integration-tests/src/main/java/androidx/RestrictToTestsAnnotationUsageJava.java
new file mode 100644
index 0000000..99fc876
--- /dev/null
+++ b/lint-checks/integration-tests/src/main/java/androidx/RestrictToTestsAnnotationUsageJava.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 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;
+
+import static androidx.annotation.RestrictTo.Scope.TESTS;
+
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/** @noinspection unused*/
+public class RestrictToTestsAnnotationUsageJava {
+    @RestrictTo(androidx.annotation.RestrictTo.Scope.TESTS)
+    public void testMethodFullyQualified() {}
+
+    @RestrictTo(RestrictTo.Scope.TESTS)
+    public void testMethodOuterClass() {}
+
+    @RestrictTo(Scope.TESTS)
+    public void testMethodInnerClass() {}
+
+    @RestrictTo(TESTS)
+    public void testMethodStaticImport() {}
+
+    @RestrictTo({Scope.TESTS, Scope.LIBRARY})
+    public void testMethodVarArg() {}
+}
diff --git a/lint-checks/integration-tests/src/main/java/androidx/RestrictToTestsAnnotationUsageKotlin.kt b/lint-checks/integration-tests/src/main/java/androidx/RestrictToTestsAnnotationUsageKotlin.kt
new file mode 100644
index 0000000..2d1622d
--- /dev/null
+++ b/lint-checks/integration-tests/src/main/java/androidx/RestrictToTestsAnnotationUsageKotlin.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 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.
+ */
+
+@file:Suppress("unused")
+
+package androidx
+
+import androidx.annotation.RestrictTo
+
+class RestrictToTestsAnnotationUsageKotlin {
+    @RestrictTo(RestrictTo.Scope.TESTS)
+    fun testMethod() {}
+
+    @RestrictTo(RestrictTo.Scope.TESTS, RestrictTo.Scope.LIBRARY)
+    fun testMethodVarArg() {}
+
+    @get:RestrictTo(RestrictTo.Scope.TESTS)
+    val testPropertyGet = "test"
+}
diff --git a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
index 9bf1025..7466c91 100644
--- a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
@@ -70,6 +70,7 @@
                 NullabilityAnnotationsDetector.ISSUE,
                 IgnoreClassLevelDetector.ISSUE,
                 ExperimentalPropertyAnnotationDetector.ISSUE,
+                BanRestrictToTestsScope.ISSUE,
                 // Temporarily disable AIDL lint check due to b/278871118.
                 // UnstableAidlAnnotationDetector.ISSUE,
                 // MissingJvmDefaultWithCompatibilityDetector is intentionally left out of the
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanRestrictToTestsScope.kt b/lint-checks/src/main/java/androidx/build/lint/BanRestrictToTestsScope.kt
new file mode 100644
index 0000000..487fd61
--- /dev/null
+++ b/lint-checks/src/main/java/androidx/build/lint/BanRestrictToTestsScope.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+@file:Suppress("UnstableApiUsage")
+
+package androidx.build.lint
+
+import com.android.tools.lint.checks.getFqName
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import org.jetbrains.kotlin.psi.KtAnnotationEntry
+import org.jetbrains.uast.UAnnotation
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UReferenceExpression
+import org.jetbrains.uast.util.isArrayInitializer
+
+class BanRestrictToTestsScope : Detector(), Detector.UastScanner {
+
+    override fun getApplicableUastTypes() = listOf(UAnnotation::class.java)
+
+    override fun createUastHandler(context: JavaContext): UElementHandler {
+        return AnnotationChecker(context)
+    }
+
+    private inner class AnnotationChecker(val context: JavaContext) : UElementHandler() {
+        override fun visitAnnotation(node: UAnnotation) {
+            if (node.qualifiedName != "androidx.annotation.RestrictTo") return
+
+            // Resolve the FQN for all arguments to value parameter.
+            val scopes = node.findAttributeValue("value")?.let { value ->
+                if (value.isArrayInitializer()) {
+                    (value as? UCallExpression)?.valueArguments?.mapNotNull { arg ->
+                        arg as? UReferenceExpression
+                    } ?: emptyList()
+                } else if (value is UReferenceExpression) {
+                    listOfNotNull(value)
+                } else {
+                    emptyList()
+                }
+            }?.mapNotNull { expr ->
+                expr.resolve()?.getFqName()
+            } ?: emptyList()
+
+            if (!scopes.contains("androidx.annotation.RestrictTo.Scope.TESTS")) return
+
+            val incident = Incident(context)
+                .issue(ISSUE)
+                .location(context.getNameLocation(node))
+                .message("Replace `@RestrictTo(TESTS)` with `@VisibleForTesting`")
+                .scope(node)
+
+            // If there's only one scope, suggest replacement.
+            if (scopes.size == 1) {
+                // Extract Kotlin use-site target, if available.
+                val useSiteTarget = (node.sourcePsi as? KtAnnotationEntry)
+                    ?.useSiteTarget
+                    ?.getAnnotationUseSiteTarget()
+                    ?.renderName
+                    ?.let { "$it:" } ?: ""
+
+                val fix = fix().name("Replace with `@${useSiteTarget}VisibleForTesting`")
+                    .replace()
+                    .with("@${useSiteTarget}androidx.annotation.VisibleForTesting")
+                    .shortenNames()
+                    .build()
+                incident.fix(fix)
+            }
+
+            context.report(incident)
+        }
+    }
+
+    companion object {
+        val ISSUE = Issue.create(
+            "UsesRestrictToTestsScope",
+            "Uses @RestrictTo(TESTS) restriction scope",
+            "Use of @RestrictTo(TESTS) restriction scope is not allowed, use " +
+                "@VisibleForTesting instead.",
+            Category.CORRECTNESS, 5, Severity.ERROR,
+            Implementation(BanRestrictToTestsScope::class.java, Scope.JAVA_FILE_SCOPE)
+        )
+    }
+}
diff --git a/lint-checks/src/test/java/androidx/build/lint/BanRestrictToTestsScopeTest.kt b/lint-checks/src/test/java/androidx/build/lint/BanRestrictToTestsScopeTest.kt
new file mode 100644
index 0000000..08720a0
--- /dev/null
+++ b/lint-checks/src/test/java/androidx/build/lint/BanRestrictToTestsScopeTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2021 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.
+ */
+
+@file:Suppress("UnstableApiUsage")
+
+package androidx.build.lint
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class BanRestrictToTestsScopeTest : AbstractLintDetectorTest(
+    useDetector = BanRestrictToTestsScope(),
+    useIssues = listOf(BanRestrictToTestsScope.ISSUE),
+    stubs = arrayOf(Stubs.RestrictTo),
+) {
+
+    @Test
+    fun `Detection of @RestrictTo(TESTS) usage in Java sources`() {
+        val input = arrayOf(
+            javaSample("androidx.RestrictToTestsAnnotationUsageJava"),
+        )
+
+        /* ktlint-disable max-line-length */
+        val expected = """
+src/androidx/RestrictToTestsAnnotationUsageJava.java:26: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo(androidx.annotation.RestrictTo.Scope.TESTS)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/androidx/RestrictToTestsAnnotationUsageJava.java:29: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo(RestrictTo.Scope.TESTS)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/androidx/RestrictToTestsAnnotationUsageJava.java:32: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo(Scope.TESTS)
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+src/androidx/RestrictToTestsAnnotationUsageJava.java:35: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo(TESTS)
+    ~~~~~~~~~~~~~~~~~~
+src/androidx/RestrictToTestsAnnotationUsageJava.java:38: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo({Scope.TESTS, Scope.LIBRARY})
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+5 errors, 0 warnings
+        """.trimIndent()
+
+        val fixDiffs = """
+Fix for src/androidx/RestrictToTestsAnnotationUsageJava.java line 26: Replace with `@VisibleForTesting`:
+@@ -26 +26
+-     @RestrictTo(androidx.annotation.RestrictTo.Scope.TESTS)
++     @androidx.annotation.VisibleForTesting
+Fix for src/androidx/RestrictToTestsAnnotationUsageJava.java line 29: Replace with `@VisibleForTesting`:
+@@ -29 +29
+-     @RestrictTo(RestrictTo.Scope.TESTS)
++     @androidx.annotation.VisibleForTesting
+Fix for src/androidx/RestrictToTestsAnnotationUsageJava.java line 32: Replace with `@VisibleForTesting`:
+@@ -32 +32
+-     @RestrictTo(Scope.TESTS)
++     @androidx.annotation.VisibleForTesting
+Fix for src/androidx/RestrictToTestsAnnotationUsageJava.java line 35: Replace with `@VisibleForTesting`:
+@@ -35 +35
+-     @RestrictTo(TESTS)
++     @androidx.annotation.VisibleForTesting
+        """.trimIndent()
+        /* ktlint-enable max-line-length */
+
+        check(*input)
+            .expect(expected)
+            .expectFixDiffs(fixDiffs)
+    }
+    @Test
+    fun `Detection of @RestrictTo(TESTS) usage in Kotlin sources`() {
+        val input = arrayOf(
+            ktSample("androidx.RestrictToTestsAnnotationUsageKotlin"),
+        )
+
+        /* ktlint-disable max-line-length */
+        val expected = """
+src/androidx/RestrictToTestsAnnotationUsageKotlin.kt:24: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo(RestrictTo.Scope.TESTS)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/androidx/RestrictToTestsAnnotationUsageKotlin.kt:27: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @RestrictTo(RestrictTo.Scope.TESTS, RestrictTo.Scope.LIBRARY)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/androidx/RestrictToTestsAnnotationUsageKotlin.kt:30: Error: Replace @RestrictTo(TESTS) with @VisibleForTesting [UsesRestrictToTestsScope]
+    @get:RestrictTo(RestrictTo.Scope.TESTS)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+3 errors, 0 warnings
+        """.trimIndent()
+
+        val fixDiffs = """
+Fix for src/androidx/RestrictToTestsAnnotationUsageKotlin.kt line 24: Replace with `@VisibleForTesting`:
+@@ -24 +24
+-     @RestrictTo(RestrictTo.Scope.TESTS)
++     @androidx.annotation.VisibleForTesting
+Fix for src/androidx/RestrictToTestsAnnotationUsageKotlin.kt line 30: Replace with `@get:VisibleForTesting`:
+@@ -30 +30
+-     @get:RestrictTo(RestrictTo.Scope.TESTS)
++     @get:androidx.annotation.VisibleForTesting
+        """.trimIndent()
+        /* ktlint-enable max-line-length */
+
+        check(*input)
+            .expect(expected)
+            .expectFixDiffs(fixDiffs)
+    }
+}
diff --git a/media/OWNERS b/media/OWNERS
index 02db238..5e87314 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -4,6 +4,7 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/media/media/build.gradle b/media/media/build.gradle
index 0787b8d..91a6177 100644
--- a/media/media/build.gradle
+++ b/media/media/build.gradle
@@ -19,7 +19,6 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("androidx.stableaidl")
 }
 
 dependencies {
@@ -47,10 +46,6 @@
 
     buildTypes.all {
         consumerProguardFiles "proguard-rules.pro"
-
-        stableAidl {
-            version 1
-        }
     }
     namespace "androidx.media"
 }
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/MediaDescriptionCompat.aidl b/media/media/src/main/aidl/android/support/v4/media/MediaDescriptionCompat.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/MediaDescriptionCompat.aidl
rename to media/media/src/main/aidl/android/support/v4/media/MediaDescriptionCompat.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/MediaMetadataCompat.aidl b/media/media/src/main/aidl/android/support/v4/media/MediaMetadataCompat.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/MediaMetadataCompat.aidl
rename to media/media/src/main/aidl/android/support/v4/media/MediaMetadataCompat.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/RatingCompat.aidl b/media/media/src/main/aidl/android/support/v4/media/RatingCompat.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/RatingCompat.aidl
rename to media/media/src/main/aidl/android/support/v4/media/RatingCompat.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/session/IMediaControllerCallback.aidl b/media/media/src/main/aidl/android/support/v4/media/session/IMediaControllerCallback.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/session/IMediaControllerCallback.aidl
rename to media/media/src/main/aidl/android/support/v4/media/session/IMediaControllerCallback.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/session/IMediaSession.aidl b/media/media/src/main/aidl/android/support/v4/media/session/IMediaSession.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/session/IMediaSession.aidl
rename to media/media/src/main/aidl/android/support/v4/media/session/IMediaSession.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/session/MediaSessionCompat.aidl b/media/media/src/main/aidl/android/support/v4/media/session/MediaSessionCompat.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/session/MediaSessionCompat.aidl
rename to media/media/src/main/aidl/android/support/v4/media/session/MediaSessionCompat.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl b/media/media/src/main/aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl
rename to media/media/src/main/aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl
diff --git a/media/media/src/main/stableAidl/android/support/v4/media/session/PlaybackStateCompat.aidl b/media/media/src/main/aidl/android/support/v4/media/session/PlaybackStateCompat.aidl
similarity index 100%
rename from media/media/src/main/stableAidl/android/support/v4/media/session/PlaybackStateCompat.aidl
rename to media/media/src/main/aidl/android/support/v4/media/session/PlaybackStateCompat.aidl
diff --git a/media/media/src/main/stableAidlImports/android/content/Intent.aidl b/media/media/src/main/stableAidlImports/android/content/Intent.aidl
deleted file mode 100644
index 0c8c241..0000000
--- a/media/media/src/main/stableAidlImports/android/content/Intent.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.content;
-
-@JavaOnlyStableParcelable parcelable Intent;
diff --git a/media/media/src/main/stableAidlImports/android/os/Bundle.aidl b/media/media/src/main/stableAidlImports/android/os/Bundle.aidl
deleted file mode 100644
index 9642d31..0000000
--- a/media/media/src/main/stableAidlImports/android/os/Bundle.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.os;
-
-@JavaOnlyStableParcelable parcelable Bundle;
diff --git a/media2/media2-common/api/aidlRelease/current/androidx/media2/common/ParcelImplListSlice.aidl b/media2/media2-common/api/aidlRelease/current/androidx/media2/common/ParcelImplListSlice.aidl
index a095df7..f4e5890 100644
--- a/media2/media2-common/api/aidlRelease/current/androidx/media2/common/ParcelImplListSlice.aidl
+++ b/media2/media2-common/api/aidlRelease/current/androidx/media2/common/ParcelImplListSlice.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/media2/media2-session/src/main/stableAidlImports/android/net/Uri.aidl b/media2/media2-session/src/main/stableAidlImports/android/net/Uri.aidl
deleted file mode 100644
index 5ec5a66..0000000
--- a/media2/media2-session/src/main/stableAidlImports/android/net/Uri.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.net;
-
-@JavaOnlyStableParcelable parcelable Uri;
diff --git a/media2/media2-session/src/main/stableAidlImports/android/os/Bundle.aidl b/media2/media2-session/src/main/stableAidlImports/android/os/Bundle.aidl
deleted file mode 100644
index 9642d31..0000000
--- a/media2/media2-session/src/main/stableAidlImports/android/os/Bundle.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.os;
-
-@JavaOnlyStableParcelable parcelable Bundle;
diff --git a/media2/media2-widget/src/main/res/values-am/strings.xml b/media2/media2-widget/src/main/res/values-am/strings.xml
index c25eb1d..e95ccd2 100644
--- a/media2/media2-widget/src/main/res/values-am/strings.xml
+++ b/media2/media2-widget/src/main/res/values-am/strings.xml
@@ -45,5 +45,5 @@
     <string name="mcv2_next_button_desc" msgid="1204572886248099893">"ቀጣይ ማህደረ መረጃ"</string>
     <string name="mcv2_rewind_button_desc" msgid="578809901971186362">"በ10 ሰከንዶች አጠንጥን"</string>
     <string name="mcv2_ffwd_button_desc" msgid="611689280746097673">"ወደፊት በ30 ሰከንዶች ሂድ"</string>
-    <string name="mcv2_full_screen_button_desc" msgid="1609817079594941003">"ሙሉ ማያ ገጽ"</string>
+    <string name="mcv2_full_screen_button_desc" msgid="1609817079594941003">"ሙሉ ማያ ገፅ"</string>
 </resources>
diff --git a/media2/media2-widget/src/main/res/values-zh-rHK/strings.xml b/media2/media2-widget/src/main/res/values-zh-rHK/strings.xml
index 7145c45..05ec6bb 100644
--- a/media2/media2-widget/src/main/res/values-zh-rHK/strings.xml
+++ b/media2/media2-widget/src/main/res/values-zh-rHK/strings.xml
@@ -29,7 +29,7 @@
     <string name="mcv2_non_music_title_unknown_text" msgid="2032814146738922144">"影片標題不明"</string>
     <string name="mcv2_music_title_unknown_text" msgid="6037645626002038645">"歌名不明"</string>
     <string name="mcv2_music_artist_unknown_text" msgid="5393558204040775454">"歌手不明"</string>
-    <string name="mcv2_playback_error_text" msgid="6061787693725630293">"無法播放您要求的影片"</string>
+    <string name="mcv2_playback_error_text" msgid="6061787693725630293">"無法播放你要求的影片"</string>
     <string name="mcv2_error_dialog_button" msgid="5940167897992933850">"好"</string>
     <string name="mcv2_back_button_desc" msgid="1540894858499118373">"返回"</string>
     <string name="mcv2_overflow_left_button_desc" msgid="2749567167276435888">"返回上一個按鈕清單"</string>
diff --git a/navigation/navigation-common-ktx/api/2.6.0-beta02.txt b/navigation/navigation-common-ktx/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common-ktx/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-common-ktx/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common-ktx/api/res-2.6.0-beta02.txt b/navigation/navigation-common-ktx/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-common-ktx/api/restricted_2.6.0-beta02.txt b/navigation/navigation-common-ktx/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common/api/2.6.0-beta02.txt b/navigation/navigation-common/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..e6d0229
--- /dev/null
+++ b/navigation/navigation-common/api/2.6.0-beta02.txt
@@ -0,0 +1,530 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(String navigatorName);
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(String uriPattern);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C> parseClassFromName(android.content.Context context, String name, Class<? extends C> expectedClassType);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract kotlin.reflect.KClass<?> value();
+    property public abstract kotlin.reflect.KClass<?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method protected <C> Class<? extends C> parseClassFromName(android.content.Context context, String name, Class<? extends C> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(String uriPattern);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination> nodes);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void clear();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public class NavGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.NavGraph> {
+    ctor public NavGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph createDestination();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]> IntArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]> LongArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]> StringArrayType;
+    field public static final androidx.navigation.NavType<java.lang.String> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D![]? get(android.os.Bundle bundle, String key);
+    method public D![] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D![]? value);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D![]? get(android.os.Bundle bundle, String key);
+    method public D![] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D![]? value);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    method public boolean popBackStack();
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+}
+
diff --git a/navigation/navigation-common/api/current.ignore b/navigation/navigation-common/api/current.ignore
deleted file mode 100644
index 8eebd5d..0000000
--- a/navigation/navigation-common/api/current.ignore
+++ /dev/null
@@ -1,9 +0,0 @@
-// Baseline format: 1.0
-InvalidNullConversion: androidx.navigation.NavType#put(android.os.Bundle, String, T) parameter #2:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter value in androidx.navigation.NavType.put(android.os.Bundle bundle, String key, T value)
-InvalidNullConversion: androidx.navigation.NavType.ParcelableType#put(android.os.Bundle, String, D) parameter #2:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter value in androidx.navigation.NavType.ParcelableType.put(android.os.Bundle bundle, String key, D value)
-
-
-RemovedClass: androidx.navigation.NavArgsLazyKt:
-    Removed class androidx.navigation.NavArgsLazyKt
diff --git a/navigation/navigation-common/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-common/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6d0229
--- /dev/null
+++ b/navigation/navigation-common/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,530 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(String navigatorName);
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(String uriPattern);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C> parseClassFromName(android.content.Context context, String name, Class<? extends C> expectedClassType);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract kotlin.reflect.KClass<?> value();
+    property public abstract kotlin.reflect.KClass<?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method protected <C> Class<? extends C> parseClassFromName(android.content.Context context, String name, Class<? extends C> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(String uriPattern);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination> nodes);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void clear();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public class NavGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.NavGraph> {
+    ctor public NavGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph createDestination();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]> IntArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]> LongArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]> StringArrayType;
+    field public static final androidx.navigation.NavType<java.lang.String> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D![]? get(android.os.Bundle bundle, String key);
+    method public D![] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D![]? value);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D![]? get(android.os.Bundle bundle, String key);
+    method public D![] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D![]? value);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    method public boolean popBackStack();
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+}
+
diff --git a/navigation/navigation-common/api/res-2.6.0-beta02.txt b/navigation/navigation-common/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-common/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-common/api/restricted_2.6.0-beta02.txt b/navigation/navigation-common/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6d0229
--- /dev/null
+++ b/navigation/navigation-common/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,530 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(String navigatorName);
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(String uriPattern);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C> parseClassFromName(android.content.Context context, String name, Class<? extends C> expectedClassType);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract kotlin.reflect.KClass<?> value();
+    property public abstract kotlin.reflect.KClass<?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method protected <C> Class<? extends C> parseClassFromName(android.content.Context context, String name, Class<? extends C> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(String uriPattern);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination> nodes);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void clear();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public class NavGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.NavGraph> {
+    ctor public NavGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph createDestination();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]> IntArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]> LongArrayType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]> StringArrayType;
+    field public static final androidx.navigation.NavType<java.lang.String> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D![]? get(android.os.Bundle bundle, String key);
+    method public D![] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D![]? value);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D![]? get(android.os.Bundle bundle, String key);
+    method public D![] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D![]? value);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    method public boolean popBackStack();
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+}
+
diff --git a/navigation/navigation-common/api/restricted_current.ignore b/navigation/navigation-common/api/restricted_current.ignore
deleted file mode 100644
index 8eebd5d..0000000
--- a/navigation/navigation-common/api/restricted_current.ignore
+++ /dev/null
@@ -1,9 +0,0 @@
-// Baseline format: 1.0
-InvalidNullConversion: androidx.navigation.NavType#put(android.os.Bundle, String, T) parameter #2:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter value in androidx.navigation.NavType.put(android.os.Bundle bundle, String key, T value)
-InvalidNullConversion: androidx.navigation.NavType.ParcelableType#put(android.os.Bundle, String, D) parameter #2:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter value in androidx.navigation.NavType.ParcelableType.put(android.os.Bundle bundle, String key, D value)
-
-
-RemovedClass: androidx.navigation.NavArgsLazyKt:
-    Removed class androidx.navigation.NavArgsLazyKt
diff --git a/navigation/navigation-compose/api/2.6.0-beta02.txt b/navigation/navigation-compose/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..73c5c5d
--- /dev/null
+++ b/navigation/navigation-compose/api/2.6.0-beta02.txt
@@ -0,0 +1,50 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+  }
+
+}
+
diff --git a/navigation/navigation-compose/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-compose/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..73c5c5d
--- /dev/null
+++ b/navigation/navigation-compose/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,50 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+  }
+
+}
+
diff --git a/navigation/navigation-compose/api/res-2.6.0-beta02.txt b/navigation/navigation-compose/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-compose/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-compose/api/restricted_2.6.0-beta02.txt b/navigation/navigation-compose/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..73c5c5d
--- /dev/null
+++ b/navigation/navigation-compose/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,50 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-fragment/api/2.6.0-beta02.txt b/navigation/navigation-dynamic-features-fragment/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..fe32d9b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/2.6.0-beta02.txt
@@ -0,0 +1,69 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-fragment/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-dynamic-features-fragment/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..fe32d9b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,69 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-fragment/api/res-2.6.0-beta02.txt b/navigation/navigation-dynamic-features-fragment/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-dynamic-features-fragment/api/restricted_2.6.0-beta02.txt b/navigation/navigation-dynamic-features-fragment/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..fe32d9b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,69 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/2.6.0-beta02.txt b/navigation/navigation-dynamic-features-runtime/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..e4c37db
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/2.6.0-beta02.txt
@@ -0,0 +1,154 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..e4c37db
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,154 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/res-2.6.0-beta02.txt b/navigation/navigation-dynamic-features-runtime/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_2.6.0-beta02.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..e4c37db
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,154 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment-ktx/api/2.6.0-beta02.txt b/navigation/navigation-fragment-ktx/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment-ktx/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-fragment-ktx/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment-ktx/api/res-2.6.0-beta02.txt b/navigation/navigation-fragment-ktx/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-fragment-ktx/api/restricted_2.6.0-beta02.txt b/navigation/navigation-fragment-ktx/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment/api/2.6.0-beta02.txt b/navigation/navigation-fragment/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..97bdfe6
--- /dev/null
+++ b/navigation/navigation-fragment/api/2.6.0-beta02.txt
@@ -0,0 +1,125 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public FragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, int containerId);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+    method @Deprecated public androidx.fragment.app.Fragment instantiateFragment(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, String className, android.os.Bundle? args);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-fragment/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..97bdfe6
--- /dev/null
+++ b/navigation/navigation-fragment/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,125 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public FragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, int containerId);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+    method @Deprecated public androidx.fragment.app.Fragment instantiateFragment(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, String className, android.os.Bundle? args);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment/api/res-2.6.0-beta02.txt b/navigation/navigation-fragment/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-fragment/api/restricted_2.6.0-beta02.txt b/navigation/navigation-fragment/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..97bdfe6
--- /dev/null
+++ b/navigation/navigation-fragment/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,125 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public FragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, int containerId);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+    method @Deprecated public androidx.fragment.app.Fragment instantiateFragment(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, String className, android.os.Bundle? args);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,? extends kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime-ktx/api/2.6.0-beta02.txt b/navigation/navigation-runtime-ktx/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime-ktx/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-runtime-ktx/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime-ktx/api/res-2.6.0-beta02.txt b/navigation/navigation-runtime-ktx/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-runtime-ktx/api/restricted_2.6.0-beta02.txt b/navigation/navigation-runtime-ktx/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime/api/2.6.0-beta02.txt b/navigation/navigation-runtime/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..39d9a7f
--- /dev/null
+++ b/navigation/navigation-runtime/api/2.6.0-beta02.txt
@@ -0,0 +1,224 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-runtime/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..6faf37c
--- /dev/null
+++ b/navigation/navigation-runtime/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,229 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method @androidx.navigation.NavDeepLinkSaveStateControl public static final void enableDeepLinkSaveState(boolean saveState);
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+    method @androidx.navigation.NavDeepLinkSaveStateControl public void enableDeepLinkSaveState(boolean saveState);
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+  }
+
+  @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavDeepLinkSaveStateControl {
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime/api/res-2.6.0-beta02.txt b/navigation/navigation-runtime/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-runtime/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-runtime/api/restricted_2.6.0-beta02.txt b/navigation/navigation-runtime/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..39d9a7f
--- /dev/null
+++ b/navigation/navigation-runtime/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,224 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-testing/api/2.6.0-beta02.txt b/navigation/navigation-testing/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..89f60a4
--- /dev/null
+++ b/navigation/navigation-testing/api/2.6.0-beta02.txt
@@ -0,0 +1,23 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState();
+    method public androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public androidx.navigation.NavBackStackEntry restoreBackStackEntry(androidx.navigation.NavBackStackEntry previouslySavedEntry);
+  }
+
+}
+
diff --git a/navigation/navigation-testing/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-testing/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..89f60a4
--- /dev/null
+++ b/navigation/navigation-testing/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,23 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState();
+    method public androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public androidx.navigation.NavBackStackEntry restoreBackStackEntry(androidx.navigation.NavBackStackEntry previouslySavedEntry);
+  }
+
+}
+
diff --git a/navigation/navigation-testing/api/res-2.6.0-beta02.txt b/navigation/navigation-testing/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-testing/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-testing/api/restricted_2.6.0-beta02.txt b/navigation/navigation-testing/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..89f60a4
--- /dev/null
+++ b/navigation/navigation-testing/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,23 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState();
+    method public androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public androidx.navigation.NavBackStackEntry restoreBackStackEntry(androidx.navigation.NavBackStackEntry previouslySavedEntry);
+  }
+
+}
+
diff --git a/navigation/navigation-ui-ktx/api/2.6.0-beta02.txt b/navigation/navigation-ui-ktx/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui-ktx/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-ui-ktx/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui-ktx/api/res-2.6.0-beta02.txt b/navigation/navigation-ui-ktx/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/res-2.6.0-beta02.txt
diff --git a/navigation/navigation-ui-ktx/api/restricted_2.6.0-beta02.txt b/navigation/navigation-ui-ktx/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui/api/2.6.0-beta02.txt b/navigation/navigation-ui/api/2.6.0-beta02.txt
new file mode 100644
index 0000000..27e99a9
--- /dev/null
+++ b/navigation/navigation-ui/api/2.6.0-beta02.txt
@@ -0,0 +1,88 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/navigation/navigation-ui/api/public_plus_experimental_2.6.0-beta02.txt b/navigation/navigation-ui/api/public_plus_experimental_2.6.0-beta02.txt
new file mode 100644
index 0000000..7cb97e2
--- /dev/null
+++ b/navigation/navigation-ui/api/public_plus_experimental_2.6.0-beta02.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method @androidx.navigation.ui.NavigationUiSaveStateControl public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    method @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController, boolean saveState);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavigationUiSaveStateControl {
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/navigation/navigation-ui/api/res-2.6.0-beta02.txt b/navigation/navigation-ui/api/res-2.6.0-beta02.txt
new file mode 100644
index 0000000..e65fdbe
--- /dev/null
+++ b/navigation/navigation-ui/api/res-2.6.0-beta02.txt
@@ -0,0 +1,8 @@
+anim nav_default_enter_anim
+anim nav_default_exit_anim
+anim nav_default_pop_enter_anim
+anim nav_default_pop_exit_anim
+animator nav_default_enter_anim
+animator nav_default_exit_anim
+animator nav_default_pop_enter_anim
+animator nav_default_pop_exit_anim
diff --git a/navigation/navigation-ui/api/restricted_2.6.0-beta02.txt b/navigation/navigation-ui/api/restricted_2.6.0-beta02.txt
new file mode 100644
index 0000000..27e99a9
--- /dev/null
+++ b/navigation/navigation-ui/api/restricted_2.6.0-beta02.txt
@@ -0,0 +1,88 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt b/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
index 0955880..78598f9 100644
--- a/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
+++ b/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
@@ -27,20 +27,22 @@
 import androidx.paging.PagingSource.LoadParams.Refresh
 import androidx.paging.PagingSource.LoadResult
 import androidx.paging.PagingSource.LoadResult.Page
-import androidx.testutils.TestDispatcher
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.StandardTestDispatcher
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(JUnit4::class)
 class LegacyPageFetcherTest {
-    private val testDispatcher = TestDispatcher()
+    private val testDispatcher = StandardTestDispatcher()
     private val data = List(9) { "$it" }
 
     inner class ImmediateListDataSource(val data: List<String>) : PagingSource<Int, String>() {
@@ -177,7 +179,7 @@
             consumer.takeStateChanges()
         )
 
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertEquals(listOf(Result(APPEND, rangeResult(6, 8))), consumer.takeResults())
         assertEquals(
@@ -204,7 +206,7 @@
             consumer.takeStateChanges()
         )
 
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertEquals(
             listOf(Result(PREPEND, rangeResult(2, 4))),
@@ -227,7 +229,7 @@
         val pager = createPager(consumer, 2, 6)
 
         pager.tryScheduleAppend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertEquals(
             listOf(
@@ -248,7 +250,7 @@
         )
 
         pager.tryScheduleAppend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertEquals(
             listOf(
@@ -275,7 +277,7 @@
         val pager = createPager(consumer, 4, 8)
 
         pager.trySchedulePrepend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertEquals(
             listOf(
@@ -295,7 +297,7 @@
         )
 
         pager.trySchedulePrepend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertEquals(
             listOf(
@@ -364,7 +366,7 @@
 
         // try a normal append first
         pager.tryScheduleAppend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(consumer.takeResults()).containsExactly(
             Result(APPEND, rangeResult(3, 5))
@@ -379,7 +381,7 @@
         pagingSource.invalidData = true
 
         pager.tryScheduleAppend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         // the load should return before returning any data
         assertThat(consumer.takeResults()).isEmpty()
@@ -400,7 +402,7 @@
 
         // try a normal prepend first
         pager.trySchedulePrepend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(consumer.takeResults()).containsExactly(
             Result(PREPEND, rangeResult(4, 6))
@@ -415,7 +417,7 @@
         pagingSource.invalidData = true
 
         pager.trySchedulePrepend()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
 
         // the load should return before returning any data
         assertThat(consumer.takeResults()).isEmpty()
diff --git a/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt b/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
index ceb1e7f..1ffe862 100644
--- a/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
+++ b/paging/paging-common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
@@ -17,7 +17,6 @@
 package androidx.paging
 
 import androidx.paging.PagingSource.LoadResult.Page
-import androidx.testutils.TestDispatcher
 import com.google.common.truth.Truth.assertThat
 import kotlin.coroutines.EmptyCoroutineContext
 import kotlinx.coroutines.Dispatchers
@@ -27,6 +26,7 @@
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.take
 import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.StandardTestDispatcher
 import org.junit.Assert
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -35,7 +35,9 @@
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
 import kotlin.test.assertTrue
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(JUnit4::class)
 class LegacyPagingSourceTest {
     private val fakePagingState = PagingState(
@@ -357,7 +359,7 @@
             }
         }
 
-        val testDispatcher = TestDispatcher()
+        val testDispatcher = StandardTestDispatcher()
         val pagingSourceFactory = dataSourceFactory.asPagingSourceFactory(
             fetchDispatcher = testDispatcher
         ).let {
@@ -365,14 +367,14 @@
         }
 
         val pagingSource0 = pagingSourceFactory()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
         assertTrue { pagingSource0.dataSource.isInvalid }
         assertTrue { pagingSource0.invalid }
         assertTrue { dataSourceFactory.dataSources[0].isInvalid }
         assertEquals(dataSourceFactory.dataSources[0], pagingSource0.dataSource)
 
         val pagingSource1 = pagingSourceFactory()
-        testDispatcher.executeAll()
+        testDispatcher.scheduler.advanceUntilIdle()
         assertFalse { pagingSource1.dataSource.isInvalid }
         assertFalse { pagingSource1.invalid }
         assertFalse { dataSourceFactory.dataSources[1].isInvalid }
diff --git a/paging/paging-common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt b/paging/paging-common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt
index 8c62bec..6f89ef0 100644
--- a/paging/paging-common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt
+++ b/paging/paging-common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.paging
 
-import androidx.testutils.TestDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -33,12 +32,11 @@
 import org.mockito.Mockito.verifyNoMoreInteractions
 import kotlin.coroutines.EmptyCoroutineContext
 import kotlin.test.assertFailsWith
+import kotlinx.coroutines.test.StandardTestDispatcher
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(JUnit4::class)
 class PageKeyedDataSourceTest {
-    private val mainThread = TestDispatcher()
-    private val backgroundThread = TestDispatcher()
-
     internal data class Item(val name: String)
 
     internal data class Page(val prev: String?, val data: List<Item>, val next: String?)
@@ -244,7 +242,7 @@
         @Suppress("UNCHECKED_CAST", "DEPRECATION")
         val boundaryCallback =
             mock(PagedList.BoundaryCallback::class.java) as PagedList.BoundaryCallback<String>
-        val dispatcher = TestDispatcher()
+        val dispatcher = StandardTestDispatcher()
 
         val testCoroutineScope = CoroutineScope(EmptyCoroutineContext)
         @Suppress("DEPRECATION")
@@ -259,7 +257,7 @@
 
         verifyNoMoreInteractions(boundaryCallback)
 
-        dispatcher.executeAll()
+        dispatcher.scheduler.advanceUntilIdle()
 
         // verify boundary callbacks are triggered
         verify(boundaryCallback).onItemAtFrontLoaded("A")
@@ -297,7 +295,7 @@
         @Suppress("UNCHECKED_CAST", "DEPRECATION")
         val boundaryCallback =
             mock(PagedList.BoundaryCallback::class.java) as PagedList.BoundaryCallback<String>
-        val dispatcher = TestDispatcher()
+        val dispatcher = StandardTestDispatcher()
 
         val testCoroutineScope = CoroutineScope(EmptyCoroutineContext)
         @Suppress("DEPRECATION")
@@ -312,7 +310,7 @@
 
         verifyNoMoreInteractions(boundaryCallback)
 
-        dispatcher.executeAll()
+        dispatcher.scheduler.advanceUntilIdle()
 
         // verify boundary callbacks are triggered
         verify(boundaryCallback).onItemAtFrontLoaded("B")
@@ -512,11 +510,4 @@
             ITEM_LIST = list
         }
     }
-
-    private fun drain() {
-        while (backgroundThread.queue.isNotEmpty() || mainThread.queue.isNotEmpty()) {
-            backgroundThread.executeAll()
-            mainThread.executeAll()
-        }
-    }
 }
diff --git a/paging/paging-common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt b/paging/paging-common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
index 9253657..adca804 100644
--- a/paging/paging-common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
+++ b/paging/paging-common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
@@ -22,7 +22,6 @@
 import androidx.paging.PageEvent.Drop
 import androidx.paging.PagingSource.LoadResult
 import androidx.testutils.MainDispatcherRule
-import androidx.testutils.TestDispatcher
 import com.google.common.truth.Truth.assertThat
 import kotlin.coroutines.ContinuationInterceptor
 import kotlin.test.assertEquals
@@ -47,6 +46,8 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.advanceTimeBy
@@ -261,12 +262,12 @@
     fun refreshOnLatestGenerationReceiver() = runTest { differ, loadDispatcher, _,
         uiReceivers, hintReceivers ->
         // first gen
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
 
         // append a page so we can cache an anchorPosition of [8]
         differ[8]
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 12)
 
@@ -279,7 +280,7 @@
         differ.refresh()
         assertThat(uiReceivers[0].refreshEvents).hasSize(1)
         assertThat(uiReceivers[1].refreshEvents).hasSize(1)
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(8 until 17)
 
@@ -301,12 +302,12 @@
         uiReceivers, hintReceivers ->
 
         // first gen
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
 
         // append a page so we can cache an anchorPosition of [8]
         differ[8]
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 12)
 
@@ -317,7 +318,7 @@
 
         // to recreate a real use-case of retry based on load error
         pagingSources[1].errorNextLoad = true
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
         // differ should still have first gen presenter
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 12)
 
@@ -325,7 +326,7 @@
         differ.retry()
         assertThat(uiReceivers[0].retryEvents).hasSize(0)
         assertThat(uiReceivers[1].retryEvents).hasSize(1)
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // will retry with the correct cached hint
         assertThat(differ.snapshot()).containsExactlyElementsIn(8 until 17)
@@ -1466,7 +1467,7 @@
         val collectLoadStates = differ.collectLoadStates()
 
         // execute queued initial REFRESH
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(50 until 59)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1477,7 +1478,7 @@
         differ.refresh()
 
         // execute second REFRESH load
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // second refresh still loads from initialKey = 50 because anchorPosition/refreshKey is null
         assertThat(pagingSources.size).isEqualTo(2)
@@ -1498,7 +1499,7 @@
         }
         val collectLoadStates = differ.collectLoadStates()
         // execute initial refresh
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(
@@ -1513,7 +1514,7 @@
         differ.refresh()
         // after a refresh, make sure the loading event comes in 1 piece w/ the end of pagination
         // reset
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(
                 refreshLocal = Loading,
@@ -1546,7 +1547,7 @@
         val collectLoadStates = differ.collectLoadStates()
 
         // initial REFRESH
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1557,7 +1558,7 @@
         // normal append
         differ[8]
 
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 12)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1572,9 +1573,9 @@
         differ[11]
         pagingSources[0].nextLoadResult = LoadResult.Invalid()
 
-        // using poll().run() instead of executeAll, otherwise this invalid APPEND + subsequent
+        // using advanceTimeBy instead of advanceUntilIdle, otherwise this invalid APPEND + subsequent
         // REFRESH will auto run consecutively and we won't be able to assert them incrementally
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceTimeBy(1001)
 
         assertThat(pagingSources.size).isEqualTo(2)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1592,7 +1593,7 @@
         )
 
         // the LoadResult.Invalid from failed APPEND triggers new pagingSource + initial REFRESH
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(11 until 20)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1608,7 +1609,7 @@
         val collectLoadStates = differ.collectLoadStates()
 
         // initial REFRESH
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(50 until 59)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1620,7 +1621,7 @@
         // normal prepend to ensure LoadStates for Page returns remains the same
         differ[0]
 
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(47 until 59)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1632,7 +1633,7 @@
         // do an invalid prepend which will return LoadResult.Invalid
         differ[0]
         pagingSources[0].nextLoadResult = LoadResult.Invalid()
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceTimeBy(1001)
 
         assertThat(pagingSources.size).isEqualTo(2)
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1645,7 +1646,7 @@
         )
 
         // the LoadResult.Invalid from failed PREPEND triggers new pagingSource + initial REFRESH
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // load starts from 0 again because the provided initialKey = 50 is not multi-generational
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
@@ -1663,7 +1664,7 @@
 
         // execute queued initial REFRESH load which will return LoadResult.Invalid()
         pagingSources[0].nextLoadResult = LoadResult.Invalid()
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceTimeBy(1001)
 
         assertThat(differ.snapshot()).isEmpty()
         assertThat(differ.newCombinedLoadStates()).containsExactly(
@@ -1673,7 +1674,7 @@
         )
 
         // execute second REFRESH load
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // second refresh still loads from initialKey = 50 because anchorPosition/refreshKey is null
         assertThat(pagingSources.size).isEqualTo(2)
@@ -1692,7 +1693,7 @@
         val collectLoadStates = differ.collectLoadStates()
 
         // initial REFRESH
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(refreshLocal = Loading),
@@ -1705,7 +1706,7 @@
         val exception = Throwable()
         pagingSources[0].nextLoadResult = LoadResult.Error(exception)
 
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(
@@ -1721,7 +1722,7 @@
 
         // retry append
         differ.retry()
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // make sure append success
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 12)
@@ -1743,7 +1744,7 @@
         val collectLoadStates = differ.collectLoadStates()
 
         // initial REFRESH
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(refreshLocal = Loading),
@@ -1757,7 +1758,7 @@
         val exception = Throwable()
         pagingSources[0].nextLoadResult = LoadResult.Error(exception)
 
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(prependLocal = Loading),
@@ -1768,7 +1769,7 @@
         // retry prepend
         differ.retry()
 
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // make sure prepend success
         assertThat(differ.snapshot()).containsExactlyElementsIn(47 until 59)
@@ -1781,14 +1782,14 @@
     }
 
     @Test
-    fun refreshError_retryLoadStates() = runTest() { differ, loadDispatcher, pagingSources, _, _ ->
+    fun refreshError_retryLoadStates() = runTest { differ, loadDispatcher, pagingSources, _, _ ->
         val collectLoadStates = differ.collectLoadStates()
 
         // initial load returns LoadResult.Error
         val exception = Throwable()
         pagingSources[0].nextLoadResult = LoadResult.Error(exception)
 
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(refreshLocal = Loading),
@@ -1799,7 +1800,7 @@
         // retry refresh
         differ.retry()
 
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // refresh retry does not trigger new gen
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
@@ -1818,7 +1819,7 @@
         val collectLoadStates = differ.collectLoadStates()
 
         // initial REFRESH
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(refreshLocal = Loading),
@@ -1832,7 +1833,7 @@
         val exception = Throwable()
         pagingSources[0].nextLoadResult = LoadResult.Error(exception)
 
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(prependLocal = Loading),
@@ -1841,7 +1842,7 @@
 
         // refresh() should reset local LoadStates and trigger new REFRESH
         differ.refresh()
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         // Initial load starts from 0 because initialKey is single gen.
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
@@ -1857,7 +1858,7 @@
     }
 
     @Test
-    fun refreshError_refreshLoadStates() = runTest() { differ, loadDispatcher, pagingSources,
+    fun refreshError_refreshLoadStates() = runTest { differ, loadDispatcher, pagingSources,
         _, _ ->
         val collectLoadStates = differ.collectLoadStates()
 
@@ -1865,7 +1866,7 @@
         val exception = Throwable()
         pagingSources[0].nextLoadResult = LoadResult.Error(exception)
 
-        loadDispatcher.executeAll()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.newCombinedLoadStates()).containsExactly(
             localLoadStatesOf(refreshLocal = Loading),
@@ -1876,7 +1877,7 @@
         // refresh should trigger new generation
         differ.refresh()
 
-        loadDispatcher.queue.poll()?.run()
+        loadDispatcher.scheduler.advanceUntilIdle()
 
         assertThat(differ.snapshot()).containsExactlyElementsIn(0 until 9)
         // Goes directly from Error --> Loading without resetting refresh to NotLoading
@@ -2038,7 +2039,7 @@
     }
 
     private fun runTest(
-        loadDispatcher: TestDispatcher = TestDispatcher(),
+        loadDispatcher: TestDispatcher = StandardTestDispatcher(),
         initialKey: Int? = null,
         pagingSources: MutableList<TestPagingSource> = mutableListOf(),
         pager: Pager<Int, Int> =
@@ -2047,7 +2048,7 @@
                 initialKey = initialKey,
                 pagingSourceFactory = {
                     TestPagingSource(
-                        loadDelay = 0,
+                        loadDelay = 1000,
                         loadContext = loadDispatcher,
                     ).also { pagingSources.add(it) }
                 }
diff --git a/playground-common/playground.properties b/playground-common/playground.properties
index 599b0b2..e17b5c1 100644
--- a/playground-common/playground.properties
+++ b/playground-common/playground.properties
@@ -26,5 +26,5 @@
 # Disable docs
 androidx.enableDocumentation=false
 androidx.playground.snapshotBuildId=9971607
-androidx.playground.metalavaBuildId=9975079
+androidx.playground.metalavaBuildId=10009114
 androidx.studio.type=playground
diff --git a/preference/preference/src/main/java/androidx/preference/PreferenceViewHolder.java b/preference/preference/src/main/java/androidx/preference/PreferenceViewHolder.java
index 8d57a15..95635c5 100644
--- a/preference/preference/src/main/java/androidx/preference/PreferenceViewHolder.java
+++ b/preference/preference/src/main/java/androidx/preference/PreferenceViewHolder.java
@@ -25,7 +25,7 @@
 import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.core.view.ViewCompat;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -61,7 +61,7 @@
     }
 
     /** @hide */
-    @RestrictTo(RestrictTo.Scope.TESTS)
+    @VisibleForTesting
     @NonNull
     public static PreferenceViewHolder createInstanceForTests(@NonNull View itemView) {
         return new PreferenceViewHolder(itemView);
diff --git a/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta04.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta04.txt
@@ -0,0 +1,92 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+  public abstract class AdIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AdIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+  public abstract class AdSelectionManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+  }
+
+  public static final class AdSelectionManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+  public abstract class AppSetIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AppSetIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+  public abstract class CustomAudienceManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+  }
+
+  public static final class CustomAudienceManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+  public abstract class MeasurementManagerFutures {
+    method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+    method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+  }
+
+  public static final class MeasurementManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+  public abstract class TopicsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+  }
+
+  public static final class TopicsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta04.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta04.txt
@@ -0,0 +1,92 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+  public abstract class AdIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AdIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+  public abstract class AdSelectionManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+  }
+
+  public static final class AdSelectionManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+  public abstract class AppSetIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AppSetIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+  public abstract class CustomAudienceManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+  }
+
+  public static final class CustomAudienceManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+  public abstract class MeasurementManagerFutures {
+    method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+    method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+  }
+
+  public static final class MeasurementManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+  public abstract class TopicsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+  }
+
+  public static final class TopicsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta04.txt
diff --git a/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta04.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta04.txt
@@ -0,0 +1,92 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+  public abstract class AdIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AdIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+  public abstract class AdSelectionManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+  }
+
+  public static final class AdSelectionManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+  public abstract class AppSetIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AppSetIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+  public abstract class CustomAudienceManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+  }
+
+  public static final class CustomAudienceManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+  public abstract class MeasurementManagerFutures {
+    method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+    method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+  }
+
+  public static final class MeasurementManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+  public abstract class TopicsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+  }
+
+  public static final class TopicsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices/api/1.0.0-beta04.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/1.0.0-beta04.txt
@@ -0,0 +1,345 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+  public final class AdId {
+    method public String getAdId();
+    method public boolean isLimitAdTrackingEnabled();
+    property public final String adId;
+    property public final boolean isLimitAdTrackingEnabled;
+  }
+
+  public abstract class AdIdManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+    method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+  }
+
+  public static final class AdIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+  public final class AdSelectionConfig {
+    ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+    method public android.net.Uri getDecisionLogicUri();
+    method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+    method public android.net.Uri getTrustedScoringSignalsUri();
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+    property public final android.net.Uri decisionLogicUri;
+    property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+    property public final android.net.Uri trustedScoringSignalsUri;
+  }
+
+  public abstract class AdSelectionManager {
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+  }
+
+  public static final class AdSelectionManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+  }
+
+  public final class AdSelectionOutcome {
+    ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+    method public long getAdSelectionId();
+    method public android.net.Uri getRenderUri();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class ReportImpressionRequest {
+    ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+    method public long getAdSelectionId();
+    property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+    property public final long adSelectionId;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+  public final class AppSetId {
+    ctor public AppSetId(String id, int scope);
+    method public String getId();
+    method public int getScope();
+    property public final String id;
+    property public final int scope;
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+    field public static final int SCOPE_APP = 1; // 0x1
+    field public static final int SCOPE_DEVELOPER = 2; // 0x2
+  }
+
+  public static final class AppSetId.Companion {
+  }
+
+  public abstract class AppSetIdManager {
+    method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+    method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+  }
+
+  public static final class AppSetIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+  public final class AdData {
+    ctor public AdData(android.net.Uri renderUri, String metadata);
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class AdSelectionSignals {
+    ctor public AdSelectionSignals(String signals);
+    method public String getSignals();
+    property public final String signals;
+  }
+
+  public final class AdTechIdentifier {
+    ctor public AdTechIdentifier(String identifier);
+    method public String getIdentifier();
+    property public final String identifier;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+  public final class CustomAudience {
+    ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+    method public android.net.Uri getBiddingLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public android.net.Uri getDailyUpdateUri();
+    method public java.time.Instant? getExpirationTime();
+    method public String getName();
+    method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+    property public final android.net.Uri biddingLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final android.net.Uri dailyUpdateUri;
+    property public final java.time.Instant? expirationTime;
+    property public final String name;
+    property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public static final class CustomAudience.Builder {
+    ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+  }
+
+  public abstract class CustomAudienceManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+  }
+
+  public static final class CustomAudienceManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+  }
+
+  public final class JoinCustomAudienceRequest {
+    ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+    property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+  }
+
+  public final class LeaveCustomAudienceRequest {
+    ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public String getName();
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final String name;
+  }
+
+  public final class TrustedBiddingData {
+    ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+    method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+    method public android.net.Uri getTrustedBiddingUri();
+    property public final java.util.List<java.lang.String> trustedBiddingKeys;
+    property public final android.net.Uri trustedBiddingUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class DeletionRequest {
+    ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+    method public int getDeletionMode();
+    method public java.util.List<android.net.Uri> getDomainUris();
+    method public java.time.Instant getEnd();
+    method public int getMatchBehavior();
+    method public java.util.List<android.net.Uri> getOriginUris();
+    method public java.time.Instant getStart();
+    property public final int deletionMode;
+    property public final java.util.List<android.net.Uri> domainUris;
+    property public final java.time.Instant end;
+    property public final int matchBehavior;
+    property public final java.util.List<android.net.Uri> originUris;
+    property public final java.time.Instant start;
+    field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+    field public static final int DELETION_MODE_ALL = 0; // 0x0
+    field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+    field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+    field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class DeletionRequest.Builder {
+    ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+  }
+
+  public static final class DeletionRequest.Companion {
+  }
+
+  public abstract class MeasurementManager {
+    ctor public MeasurementManager();
+    method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+    method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+    field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+    field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+  }
+
+  public static final class MeasurementManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceParams {
+    ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceRegistrationRequest {
+    ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+    method public android.net.Uri? getAppDestination();
+    method public android.view.InputEvent? getInputEvent();
+    method public android.net.Uri getTopOriginUri();
+    method public android.net.Uri? getVerifiedDestination();
+    method public android.net.Uri? getWebDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+    property public final android.net.Uri? appDestination;
+    property public final android.view.InputEvent? inputEvent;
+    property public final android.net.Uri topOriginUri;
+    property public final android.net.Uri? verifiedDestination;
+    property public final android.net.Uri? webDestination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+  }
+
+  public static final class WebSourceRegistrationRequest.Builder {
+    ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerParams {
+    ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerRegistrationRequest {
+    ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+    method public android.net.Uri getDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+    property public final android.net.Uri destination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean getShouldRecordObservation();
+    property public final String adsSdkName;
+    property public final boolean shouldRecordObservation;
+  }
+
+  public static final class GetTopicsRequest.Builder {
+    ctor public GetTopicsRequest.Builder();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+  }
+
+  public final class GetTopicsResponse {
+    ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+  }
+
+  public final class Topic {
+    ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+    method public long getModelVersion();
+    method public long getTaxonomyVersion();
+    method public int getTopicId();
+    property public final long modelVersion;
+    property public final long taxonomyVersion;
+    property public final int topicId;
+  }
+
+  public abstract class TopicsManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+    method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+  }
+
+  public static final class TopicsManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta04.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta04.txt
@@ -0,0 +1,345 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+  public final class AdId {
+    method public String getAdId();
+    method public boolean isLimitAdTrackingEnabled();
+    property public final String adId;
+    property public final boolean isLimitAdTrackingEnabled;
+  }
+
+  public abstract class AdIdManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+    method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+  }
+
+  public static final class AdIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+  public final class AdSelectionConfig {
+    ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+    method public android.net.Uri getDecisionLogicUri();
+    method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+    method public android.net.Uri getTrustedScoringSignalsUri();
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+    property public final android.net.Uri decisionLogicUri;
+    property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+    property public final android.net.Uri trustedScoringSignalsUri;
+  }
+
+  public abstract class AdSelectionManager {
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+  }
+
+  public static final class AdSelectionManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+  }
+
+  public final class AdSelectionOutcome {
+    ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+    method public long getAdSelectionId();
+    method public android.net.Uri getRenderUri();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class ReportImpressionRequest {
+    ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+    method public long getAdSelectionId();
+    property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+    property public final long adSelectionId;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+  public final class AppSetId {
+    ctor public AppSetId(String id, int scope);
+    method public String getId();
+    method public int getScope();
+    property public final String id;
+    property public final int scope;
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+    field public static final int SCOPE_APP = 1; // 0x1
+    field public static final int SCOPE_DEVELOPER = 2; // 0x2
+  }
+
+  public static final class AppSetId.Companion {
+  }
+
+  public abstract class AppSetIdManager {
+    method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+    method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+  }
+
+  public static final class AppSetIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+  public final class AdData {
+    ctor public AdData(android.net.Uri renderUri, String metadata);
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class AdSelectionSignals {
+    ctor public AdSelectionSignals(String signals);
+    method public String getSignals();
+    property public final String signals;
+  }
+
+  public final class AdTechIdentifier {
+    ctor public AdTechIdentifier(String identifier);
+    method public String getIdentifier();
+    property public final String identifier;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+  public final class CustomAudience {
+    ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+    method public android.net.Uri getBiddingLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public android.net.Uri getDailyUpdateUri();
+    method public java.time.Instant? getExpirationTime();
+    method public String getName();
+    method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+    property public final android.net.Uri biddingLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final android.net.Uri dailyUpdateUri;
+    property public final java.time.Instant? expirationTime;
+    property public final String name;
+    property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public static final class CustomAudience.Builder {
+    ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+  }
+
+  public abstract class CustomAudienceManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+  }
+
+  public static final class CustomAudienceManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+  }
+
+  public final class JoinCustomAudienceRequest {
+    ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+    property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+  }
+
+  public final class LeaveCustomAudienceRequest {
+    ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public String getName();
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final String name;
+  }
+
+  public final class TrustedBiddingData {
+    ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+    method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+    method public android.net.Uri getTrustedBiddingUri();
+    property public final java.util.List<java.lang.String> trustedBiddingKeys;
+    property public final android.net.Uri trustedBiddingUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class DeletionRequest {
+    ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+    method public int getDeletionMode();
+    method public java.util.List<android.net.Uri> getDomainUris();
+    method public java.time.Instant getEnd();
+    method public int getMatchBehavior();
+    method public java.util.List<android.net.Uri> getOriginUris();
+    method public java.time.Instant getStart();
+    property public final int deletionMode;
+    property public final java.util.List<android.net.Uri> domainUris;
+    property public final java.time.Instant end;
+    property public final int matchBehavior;
+    property public final java.util.List<android.net.Uri> originUris;
+    property public final java.time.Instant start;
+    field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+    field public static final int DELETION_MODE_ALL = 0; // 0x0
+    field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+    field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+    field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class DeletionRequest.Builder {
+    ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+  }
+
+  public static final class DeletionRequest.Companion {
+  }
+
+  public abstract class MeasurementManager {
+    ctor public MeasurementManager();
+    method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+    method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+    field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+    field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+  }
+
+  public static final class MeasurementManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceParams {
+    ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceRegistrationRequest {
+    ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+    method public android.net.Uri? getAppDestination();
+    method public android.view.InputEvent? getInputEvent();
+    method public android.net.Uri getTopOriginUri();
+    method public android.net.Uri? getVerifiedDestination();
+    method public android.net.Uri? getWebDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+    property public final android.net.Uri? appDestination;
+    property public final android.view.InputEvent? inputEvent;
+    property public final android.net.Uri topOriginUri;
+    property public final android.net.Uri? verifiedDestination;
+    property public final android.net.Uri? webDestination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+  }
+
+  public static final class WebSourceRegistrationRequest.Builder {
+    ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerParams {
+    ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerRegistrationRequest {
+    ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+    method public android.net.Uri getDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+    property public final android.net.Uri destination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean getShouldRecordObservation();
+    property public final String adsSdkName;
+    property public final boolean shouldRecordObservation;
+  }
+
+  public static final class GetTopicsRequest.Builder {
+    ctor public GetTopicsRequest.Builder();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+  }
+
+  public final class GetTopicsResponse {
+    ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+  }
+
+  public final class Topic {
+    ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+    method public long getModelVersion();
+    method public long getTaxonomyVersion();
+    method public int getTopicId();
+    property public final long modelVersion;
+    property public final long taxonomyVersion;
+    property public final int topicId;
+  }
+
+  public abstract class TopicsManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+    method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+  }
+
+  public static final class TopicsManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta04.txt
diff --git a/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta04.txt b/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta04.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta04.txt
@@ -0,0 +1,345 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+  public final class AdId {
+    method public String getAdId();
+    method public boolean isLimitAdTrackingEnabled();
+    property public final String adId;
+    property public final boolean isLimitAdTrackingEnabled;
+  }
+
+  public abstract class AdIdManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+    method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+  }
+
+  public static final class AdIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+  public final class AdSelectionConfig {
+    ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+    method public android.net.Uri getDecisionLogicUri();
+    method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+    method public android.net.Uri getTrustedScoringSignalsUri();
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+    property public final android.net.Uri decisionLogicUri;
+    property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+    property public final android.net.Uri trustedScoringSignalsUri;
+  }
+
+  public abstract class AdSelectionManager {
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+  }
+
+  public static final class AdSelectionManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+  }
+
+  public final class AdSelectionOutcome {
+    ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+    method public long getAdSelectionId();
+    method public android.net.Uri getRenderUri();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class ReportImpressionRequest {
+    ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+    method public long getAdSelectionId();
+    property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+    property public final long adSelectionId;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+  public final class AppSetId {
+    ctor public AppSetId(String id, int scope);
+    method public String getId();
+    method public int getScope();
+    property public final String id;
+    property public final int scope;
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+    field public static final int SCOPE_APP = 1; // 0x1
+    field public static final int SCOPE_DEVELOPER = 2; // 0x2
+  }
+
+  public static final class AppSetId.Companion {
+  }
+
+  public abstract class AppSetIdManager {
+    method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+    method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+  }
+
+  public static final class AppSetIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+  public final class AdData {
+    ctor public AdData(android.net.Uri renderUri, String metadata);
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class AdSelectionSignals {
+    ctor public AdSelectionSignals(String signals);
+    method public String getSignals();
+    property public final String signals;
+  }
+
+  public final class AdTechIdentifier {
+    ctor public AdTechIdentifier(String identifier);
+    method public String getIdentifier();
+    property public final String identifier;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+  public final class CustomAudience {
+    ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+    method public android.net.Uri getBiddingLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public android.net.Uri getDailyUpdateUri();
+    method public java.time.Instant? getExpirationTime();
+    method public String getName();
+    method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+    property public final android.net.Uri biddingLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final android.net.Uri dailyUpdateUri;
+    property public final java.time.Instant? expirationTime;
+    property public final String name;
+    property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public static final class CustomAudience.Builder {
+    ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+  }
+
+  public abstract class CustomAudienceManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+  }
+
+  public static final class CustomAudienceManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+  }
+
+  public final class JoinCustomAudienceRequest {
+    ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+    property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+  }
+
+  public final class LeaveCustomAudienceRequest {
+    ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public String getName();
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final String name;
+  }
+
+  public final class TrustedBiddingData {
+    ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+    method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+    method public android.net.Uri getTrustedBiddingUri();
+    property public final java.util.List<java.lang.String> trustedBiddingKeys;
+    property public final android.net.Uri trustedBiddingUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class DeletionRequest {
+    ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+    method public int getDeletionMode();
+    method public java.util.List<android.net.Uri> getDomainUris();
+    method public java.time.Instant getEnd();
+    method public int getMatchBehavior();
+    method public java.util.List<android.net.Uri> getOriginUris();
+    method public java.time.Instant getStart();
+    property public final int deletionMode;
+    property public final java.util.List<android.net.Uri> domainUris;
+    property public final java.time.Instant end;
+    property public final int matchBehavior;
+    property public final java.util.List<android.net.Uri> originUris;
+    property public final java.time.Instant start;
+    field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+    field public static final int DELETION_MODE_ALL = 0; // 0x0
+    field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+    field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+    field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class DeletionRequest.Builder {
+    ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+  }
+
+  public static final class DeletionRequest.Companion {
+  }
+
+  public abstract class MeasurementManager {
+    ctor public MeasurementManager();
+    method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+    method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+    field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+    field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+  }
+
+  public static final class MeasurementManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceParams {
+    ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceRegistrationRequest {
+    ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+    method public android.net.Uri? getAppDestination();
+    method public android.view.InputEvent? getInputEvent();
+    method public android.net.Uri getTopOriginUri();
+    method public android.net.Uri? getVerifiedDestination();
+    method public android.net.Uri? getWebDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+    property public final android.net.Uri? appDestination;
+    property public final android.view.InputEvent? inputEvent;
+    property public final android.net.Uri topOriginUri;
+    property public final android.net.Uri? verifiedDestination;
+    property public final android.net.Uri? webDestination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+  }
+
+  public static final class WebSourceRegistrationRequest.Builder {
+    ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerParams {
+    ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerRegistrationRequest {
+    ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+    method public android.net.Uri getDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+    property public final android.net.Uri destination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean getShouldRecordObservation();
+    property public final String adsSdkName;
+    property public final boolean shouldRecordObservation;
+  }
+
+  public static final class GetTopicsRequest.Builder {
+    ctor public GetTopicsRequest.Builder();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+  }
+
+  public final class GetTopicsResponse {
+    ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+  }
+
+  public final class Topic {
+    ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+    method public long getModelVersion();
+    method public long getTaxonomyVersion();
+    method public int getTopicId();
+    property public final long modelVersion;
+    property public final long taxonomyVersion;
+    property public final int topicId;
+  }
+
+  public abstract class TopicsManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+    method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+  }
+
+  public static final class TopicsManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+  }
+
+}
+
diff --git a/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/ProfileVerificationTestWithProfileInstallerInitializer.kt b/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/ProfileVerificationTestWithProfileInstallerInitializer.kt
index 6cbc48f..948c1f7 100644
--- a/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/ProfileVerificationTestWithProfileInstallerInitializer.kt
+++ b/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/ProfileVerificationTestWithProfileInstallerInitializer.kt
@@ -170,9 +170,14 @@
             start(ACTIVITY_NAME)
             evaluateUI {
 
-                // Taimen Api 28 and Cuttlefish Api 29 behave differently.
+                // Taimen Api 28 and Cuttlefish Api 29 behave differently and sometimes return
+                // profile non matching making this test flaky. Here we allow one of those 2
+                // results for these devices.
                 if ((isApi29 && isCuttlefish) || (isApi28 && !isCuttlefish)) {
-                    profileInstalled(RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING)
+                    profileInstalled(
+                        RESULT_CODE_COMPILED_WITH_PROFILE,
+                        RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING
+                    )
                 } else {
                     profileInstalled(RESULT_CODE_COMPILED_WITH_PROFILE)
                 }
@@ -232,9 +237,14 @@
             start(ACTIVITY_NAME)
             evaluateUI {
 
-                // Taimen Api 28 and Cuttlefish Api 29 behave differently.
+                // Taimen Api 28 and Cuttlefish Api 29 behave differently and sometimes return
+                // profile non matching making this test flaky. Here we allow one of those 2
+                // results for these devices.
                 if ((isApi29 && isCuttlefish) || (isApi28 && !isCuttlefish)) {
-                    profileInstalled(RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING)
+                    profileInstalled(
+                        RESULT_CODE_COMPILED_WITH_PROFILE,
+                        RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING
+                    )
                 } else {
                     profileInstalled(RESULT_CODE_COMPILED_WITH_PROFILE)
                 }
diff --git a/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/TestManager.kt b/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/TestManager.kt
index 3e27464..e9fb691e 100644
--- a/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/TestManager.kt
+++ b/profileinstaller/integration-tests/profile-verification/src/androidTest/java/androidx/profileinstaller/integration/profileverification/TestManager.kt
@@ -273,10 +273,10 @@
     }
 
     class AssertUiBlock(private val lines: List<String>) {
-        fun profileInstalled(resultCode: Int) =
+        fun profileInstalled(vararg resultCodes: Int) =
             assertWithMessage("Unexpected profile verification result code")
                 .that(lines[0].toInt())
-                .isEqualTo(resultCode)
+                .isIn(resultCodes.asIterable())
 
         fun hasReferenceProfile(value: Boolean) =
             assertWithMessage("Unexpected hasReferenceProfile value")
diff --git a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java
index 2669001..8b47bcd 100644
--- a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java
+++ b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java
@@ -394,6 +394,7 @@
             case Build.VERSION_CODES.S:
             case Build.VERSION_CODES.S_V2:
             case Build.VERSION_CODES.TIRAMISU:
+            case 34:
                 return ProfileVersion.V015_S;
 
             default:
@@ -429,6 +430,7 @@
             case Build.VERSION_CODES.S:
             case Build.VERSION_CODES.S_V2:
             case Build.VERSION_CODES.TIRAMISU:
+            case 34:
                 return true;
 
             default:
diff --git a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileVersion.java b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileVersion.java
index 650f8f9..fe44d97 100644
--- a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileVersion.java
+++ b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileVersion.java
@@ -33,7 +33,7 @@
     static final byte[] METADATA_V001_N = new byte[]{'0', '0', '1', '\0'};
     static final byte[] METADATA_V002 = new byte[]{'0', '0', '2', '\0'};
     public static final int MIN_SUPPORTED_SDK = Build.VERSION_CODES.N;
-    public static final int MAX_SUPPORTED_SDK = Build.VERSION_CODES.TIRAMISU;
+    public static final int MAX_SUPPORTED_SDK = 34;
 
     static String dexKeySeparator(byte[] version) {
         if (Arrays.equals(version, V001_N)) {
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index 6267016..d81c2ef 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -113,8 +113,8 @@
             configuration: "shadowAndImplementation")
 
     androidTestImplementation(project(":annotation:annotation-experimental"))
-    androidTestImplementation(project(":arch:core:core-runtime"))
-    androidTestImplementation(project(":arch:core:core-common"))
+    androidTestImplementation(projectOrArtifact(":arch:core:core-runtime"))
+    androidTestImplementation(projectOrArtifact(":arch:core:core-common"))
     androidTestImplementation(project(":room:room-testing"))
     androidTestImplementation(project(":room:room-rxjava2"))
     androidTestImplementation(project(":room:room-rxjava3"))
diff --git a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/GeneratedCodeMatchTest.kt b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/GeneratedCodeMatchTest.kt
index 5cebcec..fc964f9 100644
--- a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/GeneratedCodeMatchTest.kt
+++ b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/GeneratedCodeMatchTest.kt
@@ -16,17 +16,19 @@
 
 package androidx.room.compiler.processing.util
 
+import com.squareup.kotlinpoet.TypeSpec as KTypeSpec
 import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.XElement
+import androidx.room.compiler.processing.compat.XConverters.toXProcessing
 import com.google.common.truth.Truth.assertThat
 import com.squareup.javapoet.JavaFile
 import com.squareup.javapoet.TypeName
 import com.squareup.javapoet.TypeSpec
 import com.squareup.kotlinpoet.BOOLEAN
 import com.squareup.kotlinpoet.FileSpec
-import com.squareup.kotlinpoet.TypeSpec as KTypeSpec
 import java.io.File
-import org.junit.Test
 import org.junit.AssumptionViolatedException
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
@@ -59,6 +61,38 @@
     }
 
     @Test
+    fun successfulGeneratedJavaCodeMatchWithWriteSource() {
+        val file = JavaFile.builder(
+            "foo.bar",
+            TypeSpec.classBuilder("Baz").build()
+        ).build()
+        runTest { invocation ->
+            if (invocation.processingEnv.findTypeElement("foo.bar.Baz") == null) {
+                val originatingElements: List<XElement> =
+                    file.typeSpec.originatingElements.map {
+                        it.toXProcessing(invocation.processingEnv)
+                    }
+                invocation.processingEnv.filer.writeSource(
+                    file.packageName,
+                    file.typeSpec.name,
+                    "java",
+                    originatingElements
+                ).bufferedWriter().use {
+                    it.write(file.toString())
+                }
+            }
+            invocation.assertCompilationResult {
+                generatedSource(
+                    Source.java(
+                        "foo.bar.Baz",
+                        file.toString()
+                    )
+                )
+            }
+        }
+    }
+
+    @Test
     fun missingGeneratedCode() {
         val result = runCatching {
             runTest { invocation ->
@@ -120,6 +154,38 @@
     }
 
     @Test
+    fun successfulGeneratedKotlinCodeMatchWithWriteSource() {
+        // java environment will not generate kotlin files
+        runTest.assumeCanCompileKotlin()
+
+        val type = KTypeSpec.classBuilder("Baz").build()
+        val file = FileSpec.builder("foo.bar", "Baz")
+            .addType(type)
+            .build()
+        runTest { invocation ->
+            if (invocation.processingEnv.findTypeElement("foo.bar.Baz") == null) {
+                val originatingElements: List<XElement> =
+                    type.originatingElements.map {
+                        it.toXProcessing(invocation.processingEnv)
+                    }
+                invocation.processingEnv.filer.writeSource(
+                    file.packageName,
+                    file.name,
+                    "kt",
+                    originatingElements
+                ).bufferedWriter().use {
+                    it.write(file.toString())
+                }
+            }
+            invocation.assertCompilationResult {
+                generatedSource(
+                    Source.kotlin(combine("foo", "bar", "Baz.kt"), file.toString())
+                )
+            }
+        }
+    }
+
+    @Test
     fun successfulGeneratedKotlinCodeMatch() {
         // java environment will not generate kotlin files
         runTest.assumeCanCompileKotlin()
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt
index 533b018..46bfe08 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt
@@ -35,6 +35,22 @@
     fun write(fileSpec: FileSpec, mode: Mode = Mode.Isolating)
 
     /**
+     * Writes a source file that will be part of the output artifact (e.g. jar).
+     *
+     * Only source files should be written via this function, if the extension is not `.java` or
+     * `.kt` this function will throw an exception.
+     *
+     * @return the output stream to write the resource file.
+     */
+    fun writeSource(
+        packageName: String,
+        fileNameWithoutExtension: String,
+        extension: String,
+        originatingElements: List<XElement>,
+        mode: Mode = Mode.Isolating
+    ): OutputStream
+
+    /**
      * Writes a resource file that will be part of the output artifact (e.g. jar).
      *
      * Only non-source files should be written via this function, if the file path corresponds to a
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt
index 1874984..2e37934 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt
@@ -56,6 +56,7 @@
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticContinuationParameterElement
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticReceiverParameterElement
+import com.google.devtools.ksp.processing.Resolver
 import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
 import com.google.devtools.ksp.symbol.KSAnnotated
 import com.google.devtools.ksp.symbol.KSAnnotation
@@ -173,6 +174,9 @@
     fun XProcessingEnv.toKS(): SymbolProcessorEnvironment = (this as KspProcessingEnv).delegate
 
     @JvmStatic
+    fun XProcessingEnv.toKSResolver(): Resolver = (this as KspProcessingEnv).resolver
+
+    @JvmStatic
     fun XTypeElement.toKS(): KSClassDeclaration = (this as KspTypeElement).declaration
 
     @JvmStatic
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt
index 93578c7..2043d41 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt
@@ -46,6 +46,37 @@
         fileSpec.writeTo(delegate)
     }
 
+    override fun writeSource(
+        packageName: String,
+        fileNameWithoutExtension: String,
+        extension: String,
+        originatingElements: List<XElement>,
+        mode: XFiler.Mode
+    ): OutputStream {
+        require(extension == "java" || extension == "kt") {
+            "Source file extension must be either 'java' or 'kt', but was: $extension"
+        }
+        val javaOriginatingElements =
+            originatingElements.filterIsInstance<JavacElement>().map { it.element }.toTypedArray()
+        return when (extension) {
+            "java" -> {
+                delegate.createSourceFile(
+                    "$packageName.$fileNameWithoutExtension",
+                    *javaOriginatingElements
+                ).openOutputStream()
+            }
+            "kt" -> {
+                delegate.createResource(
+                    StandardLocation.SOURCE_OUTPUT,
+                    packageName,
+                    "$fileNameWithoutExtension.$extension",
+                    *javaOriginatingElements
+                ).openOutputStream()
+            }
+            else -> error("file type not supported: $extension")
+        }
+    }
+
     override fun writeResource(
         filePath: Path,
         originatingElements: List<XElement>,
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolver.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolver.kt
index abada70..bdade61 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolver.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolver.kt
@@ -166,10 +166,17 @@
                 }
             } else {
                 // For method parameters and var type scopes, we don't use the declaration-site
-                // variance if the last variance in the declaration-site stack was invariant and
-                // the last variance in the use-site stack was not contravariant.
-                if (typeParamStack.lastOrNull()?.variance == Variance.INVARIANT &&
-                    typeArgStack.lastOrNull()?.variance != Variance.CONTRAVARIANT) {
+                // variance if all of the following conditions apply.
+                if ( // If the last variance in the type argument stack is not contravariant
+                    typeArgStack.isNotEmpty() &&
+                    typeArgStack.last().variance != Variance.CONTRAVARIANT &&
+                    // And the type parameter stack contains at least one invariant parameter.
+                    typeParamStack.isNotEmpty() &&
+                    typeParamStack.any { it.variance == Variance.INVARIANT } &&
+                    // And the first invariant comes before the last contravariant (if any).
+                    typeParamStack.indexOfFirst { it.variance == Variance.INVARIANT } >=
+                    typeParamStack.indexOfLast { it.variance == Variance.CONTRAVARIANT }
+                ) {
                     return false
                 }
             }
@@ -218,6 +225,7 @@
         declarationType: KSType? = null,
         scope: KSTypeVarianceResolverScope,
         typeStack: ReferenceStack = ReferenceStack(),
+        typeParamStack: List<KSTypeParameter> = emptyList(),
     ): KSType {
         if (type.isError || typeStack.queue.contains(type)) {
             return type
@@ -237,9 +245,10 @@
                     type.arguments.indices.map { i ->
                         getJavaWildcardWithTypeVariablesForInnerType(
                             typeArg = type.arguments[i],
-                            declarationTypeParameter = type.declaration.typeParameters[i],
+                            typeParam = type.declaration.typeParameters[i],
                             scope = scope,
                             typeStack = typeStack,
+                            typeParamStack = typeParamStack
                         )
                     }
                 }
@@ -249,9 +258,10 @@
 
     private fun getJavaWildcardWithTypeVariablesForInnerType(
         typeArg: KSTypeArgument,
-        declarationTypeParameter: KSTypeParameter,
+        typeParam: KSTypeParameter,
         scope: KSTypeVarianceResolverScope,
         typeStack: ReferenceStack,
+        typeParamStack: List<KSTypeParameter>,
     ): KSTypeArgument {
         val type = typeArg.type?.resolve()
         if (
@@ -266,9 +276,20 @@
             type = type,
             scope = scope,
             typeStack = typeStack,
+            typeParamStack = typeParamStack + typeParam,
         )
-        val resolvedVariance = if (declarationTypeParameter.variance != Variance.INVARIANT) {
-            declarationTypeParameter.variance
+        val resolvedVariance = if (
+            typeParam.variance != Variance.INVARIANT &&
+            // This is a weird rule, but empirically whether or not we inherit type variance in
+            // this case depends on the scope of the type used when calling asMemberOf. For
+            // example, if XMethodElement#asMemberOf(XType) is called with an XType that has no
+            // scope or has a matching method scope then we inherit the parameter variance; however,
+            // if asMemberOf was called with an XType that was from a different scope we only
+            // inherit variance here if there is at least one contravariant in the param stack.
+            (scope.asMemberOfScopeOrSelf() == scope ||
+                typeParamStack.any { it.variance == Variance.CONTRAVARIANT })
+        ) {
+            typeParam.variance
         } else {
             typeArg.variance
         }
@@ -296,8 +317,7 @@
             scope = scope,
             typeStack = typeStack
         )
-        val resolvedVariance = if (declarationTypeArg.variance != Variance.INVARIANT &&
-            (!scope.isValOrReturnType() || declarationTypeArg.variance != Variance.COVARIANT)) {
+        val resolvedVariance = if (declarationTypeArg.variance != Variance.INVARIANT) {
             declarationTypeArg.variance
         } else {
             typeArg.variance
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverScope.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverScope.kt
index 9b4c646..f39ab11 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverScope.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverScope.kt
@@ -28,7 +28,8 @@
  */
 internal sealed class KSTypeVarianceResolverScope(
     private val annotated: KSAnnotated,
-    private val container: KSDeclaration?
+    private val container: KSDeclaration?,
+    private val asMemberOf: KspType?
 ) {
     /**
      * Checks whether we need wildcard resolution at all. It is only necessary if either the method
@@ -58,12 +59,18 @@
     /** Returns `true` if this scope represents a val property or a return type. */
     abstract fun isValOrReturnType(): Boolean
 
+    /** Returns the scope of the `asMemberOf` container type. */
+    fun asMemberOfScopeOrSelf(): KSTypeVarianceResolverScope? {
+        return asMemberOf?.scope ?: this
+    }
+
     internal class MethodParameter(
         private val kspExecutableElement: KspExecutableElement,
         private val parameterIndex: Int,
         annotated: KSAnnotated,
         container: KSDeclaration?,
-    ) : KSTypeVarianceResolverScope(annotated, container) {
+        asMemberOf: KspType?,
+    ) : KSTypeVarianceResolverScope(annotated, container, asMemberOf) {
         override fun declarationType() =
             (kspExecutableElement.parameters[parameterIndex].type as KspType).ksType
 
@@ -71,10 +78,12 @@
     }
 
     internal class PropertySetterParameterType(
-        private val setterMethod: KspSyntheticPropertyMethodElement.Setter
+        private val setterMethod: KspSyntheticPropertyMethodElement.Setter,
+        asMemberOf: KspType?,
     ) : KSTypeVarianceResolverScope(
         annotated = setterMethod.accessor,
-        container = setterMethod.field.enclosingElement.declaration
+        container = setterMethod.field.enclosingElement.declaration,
+        asMemberOf = asMemberOf,
     ) {
         override fun declarationType(): KSType {
             // We return the declaration from the setter, not the field because the setter parameter
@@ -86,10 +95,12 @@
     }
 
     internal class PropertyGetterMethodReturnType(
-        private val getterMethod: KspSyntheticPropertyMethodElement.Getter
+        private val getterMethod: KspSyntheticPropertyMethodElement.Getter,
+        asMemberOf: KspType?,
     ) : KSTypeVarianceResolverScope(
         annotated = getterMethod.accessor,
-        container = getterMethod.field.enclosingElement.declaration
+        container = getterMethod.field.enclosingElement.declaration,
+        asMemberOf = asMemberOf,
     ) {
         override fun declarationType(): KSType {
             // We return the declaration from the getter, not the field because the getter return
@@ -100,18 +111,26 @@
         override fun isValOrReturnType() = true
     }
 
-    internal class PropertyType(val field: KspFieldElement) : KSTypeVarianceResolverScope(
+    internal class PropertyType(
+        val field: KspFieldElement,
+        asMemberOf: KspType?,
+    ) : KSTypeVarianceResolverScope(
         annotated = field.declaration,
-        container = field.enclosingElement.declaration
+        container = field.enclosingElement.declaration,
+        asMemberOf = asMemberOf,
     ) {
         override fun declarationType() = field.type.ksType
 
         override fun isValOrReturnType() = field.isFinal()
     }
 
-    internal class MethodReturnType(val method: KspMethodElement) : KSTypeVarianceResolverScope(
+    internal class MethodReturnType(
+        val method: KspMethodElement,
+        asMemberOf: KspType?,
+    ) : KSTypeVarianceResolverScope(
         annotated = method.declaration,
-        container = method.enclosingElement.declaration
+        container = method.enclosingElement.declaration,
+        asMemberOf = asMemberOf,
     ) {
         override fun declarationType() = method.returnType.ksType
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
index 84cf572..a840aa4 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -24,7 +24,6 @@
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
 import com.google.devtools.ksp.symbol.KSFunctionDeclaration
 import com.google.devtools.ksp.symbol.KSPropertySetter
-import com.google.devtools.ksp.symbol.KSType
 import com.google.devtools.ksp.symbol.KSValueParameter
 
 internal class KspExecutableParameterElement(
@@ -48,7 +47,7 @@
         get() = parameter.hasDefault
 
     override val type: KspType by lazy {
-        asMemberOf(enclosingElement.enclosingElement.type?.ksType)
+        createAsMemberOf(closestMemberContainer.type)
     }
 
     override val closestMemberContainer: XMemberContainer by lazy {
@@ -59,26 +58,28 @@
         get() = "$name in ${enclosingElement.fallbackLocationText}"
 
     override fun asMemberOf(other: XType): KspType {
-        if (closestMemberContainer.type?.isSameType(other) != false) {
-            return type
+        return if (closestMemberContainer.type?.isSameType(other) != false) {
+            type
+        } else {
+            createAsMemberOf(other)
         }
-        check(other is KspType)
-        return asMemberOf(other.ksType)
     }
 
-    private fun asMemberOf(ksType: KSType?): KspType {
+    private fun createAsMemberOf(container: XType?): KspType {
+        check(container is KspType?)
         return env.wrap(
             originatingReference = parameter.type,
             ksType = parameter.typeAsMemberOf(
                 functionDeclaration = enclosingElement.declaration,
-                ksType = ksType
+                ksType = container?.ksType
             )
         ).copyWithScope(
             KSTypeVarianceResolverScope.MethodParameter(
                 kspExecutableElement = enclosingElement,
                 parameterIndex = parameterIndex,
                 annotated = parameter.type,
-                container = ksType?.declaration
+                container = container?.ksType?.declaration,
+                asMemberOf = container,
             )
         )
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
index b8bad187..beab250 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
@@ -24,7 +24,6 @@
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
 import com.google.devtools.ksp.isPrivate
 import com.google.devtools.ksp.symbol.KSPropertyDeclaration
-import com.google.devtools.ksp.symbol.KSType
 import com.google.devtools.ksp.symbol.Modifier
 
 internal class KspFieldElement(
@@ -48,7 +47,7 @@
     }
 
     override val type: KspType by lazy {
-        asMemberOf(enclosingElement.type?.ksType)
+        createAsMemberOf(closestMemberContainer.type)
     }
 
     override val jvmDescriptor: String
@@ -92,18 +91,24 @@
         }
 
     override fun asMemberOf(other: XType): KspType {
-        if (enclosingElement.type?.isSameType(other) != false) {
-            return type
+        return if (closestMemberContainer.type?.isSameType(other) != false) {
+            type
+        } else {
+            return createAsMemberOf(other)
         }
-        check(other is KspType)
-        return asMemberOf(other.ksType)
     }
 
-    private fun asMemberOf(ksType: KSType?): KspType {
+    private fun createAsMemberOf(container: XType?): KspType {
+        check(container is KspType?)
         return env.wrap(
             originatingReference = declaration.type,
-            ksType = declaration.typeAsMemberOf(ksType)
-        ).copyWithScope(KSTypeVarianceResolverScope.PropertyType(this))
+            ksType = declaration.typeAsMemberOf(container?.ksType)
+        ).copyWithScope(
+            KSTypeVarianceResolverScope.PropertyType(
+                field = this,
+                asMemberOf = container,
+            )
+        )
     }
 
     companion object {
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
index 7c92ac3..0c04d79 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
@@ -75,6 +75,28 @@
         }
     }
 
+    override fun writeSource(
+        packageName: String,
+        fileNameWithoutExtension: String,
+        extension: String,
+        originatingElements: List<XElement>,
+        mode: XFiler.Mode
+    ): OutputStream {
+        require(extension == "java" || extension == "kt") {
+            "Source file extension must be either 'java' or 'kt', but was: $extension"
+        }
+        val kspFilerOriginatingElements = originatingElements
+            .mapNotNull { it.originatingElementForPoet() }
+            .toOriginatingElements()
+        return createNewFile(
+            originatingElements = kspFilerOriginatingElements,
+            packageName = packageName,
+            fileName = fileNameWithoutExtension,
+            extensionName = extension,
+            aggregating = mode == XFiler.Mode.Aggregating
+        )
+    }
+
     override fun writeResource(
         filePath: Path,
         originatingElements: List<XElement>,
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
index 131b645..841154a 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
@@ -122,7 +122,12 @@
             declaration.returnKspType(
                 env = env,
                 containing = enclosingElement.type
-            ).copyWithScope(KSTypeVarianceResolverScope.MethodReturnType(this))
+            ).copyWithScope(
+                KSTypeVarianceResolverScope.MethodReturnType(
+                    method = this,
+                    asMemberOf = enclosingElement.type,
+                )
+            )
         }
         override fun isSuspendFunction() = false
     }
@@ -137,7 +142,12 @@
             env.wrap(
                 ksType = env.resolver.builtIns.anyType.makeNullable(),
                 allowPrimitives = false
-            ).copyWithScope(KSTypeVarianceResolverScope.MethodReturnType(this))
+            ).copyWithScope(
+                KSTypeVarianceResolverScope.MethodReturnType(
+                    method = this,
+                    asMemberOf = enclosingElement.type
+                )
+            )
         }
 
         override val parameters: List<XExecutableParameterElement>
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
index fba2cbc..600bb01 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
@@ -47,7 +47,12 @@
             origin.declaration.returnKspType(
                 env = env,
                 containing = containing
-            ).copyWithScope(KSTypeVarianceResolverScope.MethodReturnType(origin))
+            ).copyWithScope(
+                KSTypeVarianceResolverScope.MethodReturnType(
+                    method = origin,
+                    asMemberOf = containing
+                )
+            )
         }
     }
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index 8fc4f16..74709b2 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -52,7 +52,7 @@
     /**
      * Type resolver to convert KSType into its JVM representation.
      */
-    protected val scope: KSTypeVarianceResolverScope?
+    val scope: KSTypeVarianceResolverScope?
 ) : KspAnnotated(env), XType, XEquality {
     override val rawType by lazy {
         KspRawType(this)
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
index 1fbc669..de2c250 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
@@ -30,7 +30,6 @@
 import androidx.room.compiler.processing.ksp.requireContinuationClass
 import androidx.room.compiler.processing.ksp.returnTypeAsMemberOf
 import androidx.room.compiler.processing.ksp.swapResolvedType
-import com.google.devtools.ksp.symbol.KSType
 import com.google.devtools.ksp.symbol.Variance
 
 /**
@@ -75,7 +74,7 @@
         get() = false
 
     override val type: KspType by lazy {
-        asMemberOf(enclosingElement.enclosingElement.type?.ksType)
+        createAsMemberOf(closestMemberContainer.type)
     }
 
     override val fallbackLocationText: String
@@ -89,17 +88,18 @@
     }
 
     override fun asMemberOf(other: XType): KspType {
-        if (enclosingElement.enclosingElement.type?.isSameType(other) != false) {
-            return type
+        return if (closestMemberContainer.type?.isSameType(other) != false) {
+            type
+        } else {
+            createAsMemberOf(other)
         }
-        check(other is KspType)
-        return asMemberOf(other.ksType)
     }
 
-    private fun asMemberOf(ksType: KSType?): KspType {
+    private fun createAsMemberOf(container: XType?): KspType {
+        check(container is KspType?)
         val continuation = env.resolver.requireContinuationClass()
         val asMember = enclosingElement.declaration.returnTypeAsMemberOf(
-            ksType = ksType
+            ksType = container?.ksType
         )
         val returnTypeRef = checkNotNull(enclosingElement.declaration.returnType) {
             "cannot find return type reference for $this"
@@ -119,7 +119,8 @@
                 kspExecutableElement = enclosingElement,
                 parameterIndex = enclosingElement.parameters.size - 1,
                 annotated = enclosingElement.declaration,
-                container = ksType?.declaration
+                container = container?.ksType?.declaration,
+                asMemberOf = container
             )
         )
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index b5e1a70..2067b96 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -34,6 +34,7 @@
 import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_SET_PARAM
 import androidx.room.compiler.processing.ksp.KspFieldElement
 import androidx.room.compiler.processing.ksp.KspHasModifiers
+import androidx.room.compiler.processing.ksp.KspMemberContainer
 import androidx.room.compiler.processing.ksp.KspProcessingEnv
 import androidx.room.compiler.processing.ksp.KspType
 import androidx.room.compiler.processing.ksp.findEnclosingMemberContainer
@@ -84,7 +85,7 @@
 
     final override fun isExtensionFunction() = false
 
-    final override val enclosingElement: XMemberContainer
+    final override val enclosingElement: KspMemberContainer
         get() = this.field.enclosingElement
 
     final override val closestMemberContainer: XMemberContainer by lazy {
@@ -119,6 +120,7 @@
     }
 
     final override fun asMemberOf(other: XType): XMethodType {
+        check(other is KspType)
         return KspSyntheticPropertyMethodType.create(
             env = env,
             element = this,
@@ -168,7 +170,10 @@
 
         override val returnType: XType by lazy {
             field.type.copyWithScope(
-                KSTypeVarianceResolverScope.PropertyGetterMethodReturnType(this)
+                KSTypeVarianceResolverScope.PropertyGetterMethodReturnType(
+                    getterMethod = this,
+                    asMemberOf = enclosingElement.type,
+                )
             )
         }
 
@@ -247,7 +252,10 @@
 
             override val type: KspType by lazy {
                 enclosingElement.field.type.copyWithScope(
-                    KSTypeVarianceResolverScope.PropertySetterParameterType(enclosingElement)
+                    KSTypeVarianceResolverScope.PropertySetterParameterType(
+                        setterMethod = enclosingElement,
+                        asMemberOf = enclosingElement.enclosingElement.type,
+                    )
                 )
             }
 
@@ -262,9 +270,16 @@
             }
 
             override fun asMemberOf(other: XType): KspType {
+                if (closestMemberContainer.type?.isSameType(other) != false) {
+                    return type
+                }
+                check(other is KspType)
                 return enclosingElement.field.asMemberOf(other)
                     .copyWithScope(
-                        KSTypeVarianceResolverScope.PropertySetterParameterType(enclosingElement)
+                        KSTypeVarianceResolverScope.PropertySetterParameterType(
+                            setterMethod = enclosingElement,
+                            asMemberOf = other,
+                        )
                     )
             }
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
index a482093..d1bd312 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
@@ -21,6 +21,7 @@
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.ksp.KSTypeVarianceResolverScope
 import androidx.room.compiler.processing.ksp.KspProcessingEnv
+import androidx.room.compiler.processing.ksp.KspType
 import com.google.devtools.ksp.symbol.KSPropertyGetter
 import com.google.devtools.ksp.symbol.KSPropertySetter
 import com.squareup.javapoet.TypeVariableName
@@ -61,7 +62,7 @@
         fun create(
             env: KspProcessingEnv,
             element: KspSyntheticPropertyMethodElement,
-            container: XType?
+            container: KspType?
         ): XMethodType {
             return when (element.accessor) {
                 is KSPropertyGetter ->
@@ -84,7 +85,7 @@
     private class Getter(
         env: KspProcessingEnv,
         origin: KspSyntheticPropertyMethodElement,
-        containingType: XType?
+        containingType: KspType?
     ) : KspSyntheticPropertyMethodType(
         env = env,
         origin = origin,
@@ -97,7 +98,8 @@
                 origin.field.asMemberOf(containingType)
             }.copyWithScope(
                 KSTypeVarianceResolverScope.PropertyGetterMethodReturnType(
-                    getterMethod = origin as KspSyntheticPropertyMethodElement.Getter
+                    getterMethod = origin as KspSyntheticPropertyMethodElement.Getter,
+                    asMemberOf = containingType
                 )
             )
         }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt
index 94224fe..0ebf74c 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt
@@ -26,7 +26,6 @@
 import androidx.room.compiler.processing.ksp.KspMethodElement
 import androidx.room.compiler.processing.ksp.KspProcessingEnv
 import androidx.room.compiler.processing.ksp.KspType
-import com.google.devtools.ksp.symbol.KSType
 import com.google.devtools.ksp.symbol.KSTypeReference
 
 internal class KspSyntheticReceiverParameterElement(
@@ -60,7 +59,7 @@
         get() = false
 
     override val type: KspType by lazy {
-        asMemberOf(enclosingElement.enclosingElement.type?.ksType)
+        createAsMemberOf(closestMemberContainer.type)
     }
 
     override val fallbackLocationText: String
@@ -74,19 +73,20 @@
     }
 
     override fun asMemberOf(other: XType): KspType {
-        if (closestMemberContainer.type?.isSameType(other) != false) {
-            return type
+        return if (closestMemberContainer.type?.isSameType(other) != false) {
+            type
+        } else {
+            createAsMemberOf(other)
         }
-        check(other is KspType)
-        return asMemberOf(other.ksType)
     }
 
-    private fun asMemberOf(ksType: KSType?): KspType {
+    private fun createAsMemberOf(container: XType?): KspType {
+        check(container is KspType?)
         val asMemberReceiverType = receiverType.resolve().let {
-            if (ksType == null || it.isError) {
+            if (container?.ksType == null || it.isError) {
                 return@let it
             }
-            val asMember = enclosingElement.declaration.asMemberOf(ksType)
+            val asMember = enclosingElement.declaration.asMemberOf(container?.ksType)
             checkNotNull(asMember.extensionReceiverType)
         }
         return env.wrap(
@@ -97,7 +97,8 @@
                 kspExecutableElement = enclosingElement,
                 parameterIndex = 0, // Receiver param is the 1st one
                 annotated = enclosingElement.declaration,
-                container = ksType?.declaration
+                container = container?.ksType?.declaration,
+                asMemberOf = container
             )
         )
     }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverWithTypeParametersTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverWithTypeParametersTest.kt
new file mode 100644
index 0000000..16b8f8c
--- /dev/null
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeVarianceResolverWithTypeParametersTest.kt
@@ -0,0 +1,179 @@
+/*
+ * 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.room.compiler.processing.ksp
+
+import androidx.room.compiler.processing.XMethodType
+import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.getDeclaredMethodByJvmName
+import androidx.room.compiler.processing.util.runKaptTest
+import androidx.room.compiler.processing.util.runKspTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class KSTypeVarianceResolverWithTypeParametersTest(
+    private val t0: String,
+    private val t1: String,
+    private val t2: String,
+    private val t3: String,
+    private val t4: String,
+) {
+    @Test
+    fun testResults() {
+        // Note: The compilation results for all parameters of this parameterized test are
+        // calculated at the same time (on the first call to compilationResults) because its much
+        // faster to compile the sources all together rather than once per parameter. However,
+        // there's still benefit to keeping this test parameterized since it makes it easier to
+        // parse breakages due to a particular parameter.
+        val key = key(t0, t1, t2, t3, t4)
+        assertThat(compilationResults.kspSignaturesMap[key])
+            .containsExactlyElementsIn(compilationResults.kaptSignaturesMap[key])
+            .inOrder()
+    }
+
+    private companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}-{1}-{2}-{3}-{4}")
+        fun params(): List<Array<String>> {
+            val genericTypes = listOf("Foo", "FooIn", "FooOut")
+            val parameters: MutableList<Array<String>> = mutableListOf()
+            for (t0 in genericTypes) {
+                for (t1 in genericTypes) {
+                    for (t2 in genericTypes) {
+                        for (t3 in genericTypes) {
+                            for (t4 in genericTypes) {
+                                parameters.add(arrayOf(t0, t1, t2, t3, t4))
+                            }
+                        }
+                    }
+                }
+            }
+            return parameters
+        }
+
+        val compilationResults: CompilationResults by lazy {
+            val sourcesMap = params().associate { (t0, t1, t2, t3, t4) ->
+                val key = key(t0, t1, t2, t3, t4)
+                key to listOf(
+                    source("${key}0", "T", t = "$t0<$t1<$t2<$t3<$t4<Bar>>>>>"),
+                    source("${key}1", "$t0<T>", t = "$t1<$t2<$t3<$t4<Bar>>>>"),
+                    source("${key}2", "$t0<$t1<T>>", t = "$t2<$t3<$t4<Bar>>>"),
+                    source("${key}3", "$t0<$t1<$t2<T>>>", t = "$t3<$t4<Bar>>"),
+                    source("${key}4", "$t0<$t1<$t2<$t3<T>>>>", t = "$t4<Bar>"),
+                    source("${key}5", "$t0<$t1<$t2<$t3<$t4<T>>>>>", t = "Bar"),
+                )
+            }
+            val sources = sourcesMap.values.flatten() + Source.kotlin(
+                "SharedInterfaces.kt",
+                """
+                interface Foo<T>
+                interface FooIn<in T>
+                interface FooOut<out T>
+                interface Bar
+                """.trimIndent()
+            )
+            val kaptSignaturesMap = buildMap(sourcesMap.size) {
+                runKaptTest(sources) {
+                    sourcesMap.keys.forEach { key ->
+                        put(key, IntRange(0, 5).flatMap { i -> collectSignatures(it, key, i) })
+                    }
+                }
+            }
+            val kspSignaturesMap = buildMap(sourcesMap.size) {
+                runKspTest(sources) {
+                    sourcesMap.keys.forEach { key ->
+                        put(key, IntRange(0, 5).flatMap { i -> collectSignatures(it, key, i) })
+                    }
+                }
+            }
+            CompilationResults(kaptSignaturesMap, kspSignaturesMap)
+        }
+
+        private fun source(suffix: String, type: String, t: String): Source {
+            val sub = "Sub$suffix"
+            val base = "Base$suffix"
+            return Source.kotlin(
+                "$sub.kt",
+                """
+                class $sub: $base<$t>() {
+                    fun subMethod(param: $base<$t>): $base<$t> = TODO()
+                }
+                open class $base<T> {
+                    fun baseMethod(param: $type): $type = TODO()
+                }
+                """.trimIndent()
+            )
+        }
+
+        private fun collectSignatures(
+            invocation: XTestInvocation,
+            key: String,
+            configuration: Int,
+        ): List<String> {
+            val subName = "Sub$key$configuration"
+            val baseName = "Base$key$configuration"
+            val sub = invocation.processingEnv.requireTypeElement(subName)
+            val subMethod = sub.getDeclaredMethodByJvmName("subMethod")
+            val subSuperclassType = sub.superClass!!
+            val subMethodParamType = subMethod.parameters.single().type
+            val subMethodReturnType = subMethod.returnType
+            val base = invocation.processingEnv.requireTypeElement(baseName)
+            // Note: For each method/field we test its signature when resolved asMemberOf from a
+            // subtype, super class, param type, and return type, as we may get different signatures
+            // depending on the scope of the type used with asMemberOf.
+            return buildList {
+                base.getDeclaredMethods().forEach { method ->
+                    fun XMethodType.signature(): String {
+                        val returnType = returnType.typeName
+                        val parameters = parameterTypes.map { it.typeName }
+                        return "${method.name} : $returnType : $parameters"
+                    }
+                    val fromSubType = method.asMemberOf(sub.type)
+                    val fromSuperClassType = method.asMemberOf(subSuperclassType)
+                    val fromParamType = method.asMemberOf(subMethodParamType)
+                    val fromReturnType = method.asMemberOf(subMethodReturnType)
+                    add("$configuration-fromSub-${fromSubType.signature()}")
+                    add("$configuration-fromSuperClass-${fromSuperClassType.signature()}")
+                    add("$configuration-fromParam-${fromParamType.signature()}")
+                    add("$configuration-fromReturnType-${fromReturnType.signature()}")
+                }
+                base.getDeclaredFields().forEach { field ->
+                    fun XType.signature() = "${field.name} : $typeName"
+                    val fromSubType = field.asMemberOf(sub.type)
+                    val fromSuperClassType = field.asMemberOf(subSuperclassType)
+                    val fromParamType = field.asMemberOf(subMethodParamType)
+                    val fromReturnType = field.asMemberOf(subMethodReturnType)
+                    add("$configuration-fromSub-${fromSubType.signature()}")
+                    add("$configuration-fromSuperClass-${fromSuperClassType.signature()}")
+                    add("$configuration-fromParam-${fromParamType.signature()}")
+                    add("$configuration-fromReturnType-${fromReturnType.signature()}")
+                }
+            }
+        }
+
+        fun key(t0: String, t1: String, t2: String, t3: String, t4: String) = "$t0$t1$t2$t3$t4"
+
+        data class CompilationResults(
+            val kaptSignaturesMap: Map<String, List<String>>,
+            val kspSignaturesMap: Map<String, List<String>>,
+        )
+    }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 1a50a33..50f046f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -202,11 +202,6 @@
 }
 
 private String getRequestedProjectSubsetName() {
-    def prop = providers.gradleProperty("androidx.projects")
-    if (prop.isPresent()) {
-        return prop.get().toUpperCase()
-    }
-
     def envProp = providers.environmentVariable("ANDROIDX_PROJECTS")
     if (envProp.isPresent()) {
         return envProp.get().toUpperCase()
@@ -214,8 +209,15 @@
     return null
 }
 
+private String getRequestedProjectPrefix() {
+    def envProp = providers.environmentVariable("PROJECT_PREFIX")
+    if (envProp.isPresent()) {
+        return envProp.get()
+    }
+    return null
+}
+
 boolean isAllProjects() {
-    String projectSubsetName = getRequestedProjectSubsetName()
     return requestedProjectSubsetName == null || requestedProjectSubsetName == "ALL"
 }
 
@@ -313,10 +315,12 @@
 @Field Map<String, File> allProjects = new HashMap<String, File>()
 // A set of projects that the user asked to filter to.
 @Field Set<String> filteredProjects = new HashSet<String>()
+filteredProjects.add(":lint-checks")
 
 @Field Pattern projectReferencePattern = Pattern.compile(
         "(project|projectOrArtifact)\\((path: )?[\"'](?<name>\\S*)[\"'](, configuration: .*)?\\)"
 )
+@Field Pattern multilineProjectReference = Pattern.compile("project\\(\$")
 @Field Pattern inspection = Pattern.compile("packageInspector\\(project, \"(.*)\"\\)")
 @Field Pattern composePlugin = Pattern.compile("id\\(\"AndroidXComposePlugin\"\\)")
 @Field Pattern paparazziPlugin = Pattern.compile("id\\(\"AndroidXPaparazziPlugin\"\\)")
@@ -331,8 +335,10 @@
 //   the project name in the IDE
 //   the Maven artifactId
 //
-def includeProject(name, filePath, List<BuildType> filter = []) {
-    if (shouldIncludeForFilter(filter)) filteredProjects.add(name)
+def includeProject(String name, filePath, List<BuildType> filter = []) {
+    if (getRequestedProjectPrefix() != null) {
+        if (name.startsWith(getRequestedProjectPrefix())) filteredProjects.add(name)
+    } else if (shouldIncludeForFilter(filter)) filteredProjects.add(name)
     def file
     if (filePath != null) {
         if (filePath instanceof String) {
@@ -349,12 +355,19 @@
     allProjects[name] = file
     File buildGradle = new File(file, "build.gradle")
     if (buildGradle.exists()) {
+        def buildGradleProperty = settings.services.get(ObjectFactory).fileProperty().fileValue(buildGradle)
+        def contents = settings.providers.fileContents(buildGradleProperty).getAsText().get()
         Set<String> links = new HashSet<String>()
-        for (line in buildGradle.readLines()) {
+        for (line in contents.lines()) {
             Matcher m = projectReferencePattern.matcher(line)
             if (m.find()) {
                 links.add(m.group("name"))
             }
+            if (multilineProjectReference.matcher(line).find()) {
+                throw new IllegalStateException(
+                        "Multi-line project() references are not supported. Please fix $file.absolutePath"
+                )
+            }
             Matcher matcherInspection = inspection.matcher(line)
             if (matcherInspection) {
                 links.add(matcherInspection.group(1))
@@ -426,8 +439,8 @@
 includeProject(":appsearch:appsearch-local-storage", [BuildType.MAIN])
 includeProject(":appsearch:appsearch-platform-storage", [BuildType.MAIN])
 includeProject(":appsearch:appsearch-test-util", [BuildType.MAIN])
-includeProject(":arch:core:core-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":arch:core:core-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":arch:core:core-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":arch:core:core-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":arch:core:core-testing", [BuildType.MAIN])
 includeProject(":asynclayoutinflater:asynclayoutinflater", [BuildType.MAIN])
 includeProject(":asynclayoutinflater:asynclayoutinflater-appcompat", [BuildType.MAIN])
@@ -524,9 +537,9 @@
 includeProject(":compose:animation:animation-graphics:animation-graphics-samples", "compose/animation/animation-graphics/samples", [BuildType.COMPOSE])
 includeProject(":compose:benchmark-utils", [BuildType.COMPOSE])
 includeProject(":compose:benchmark-utils:benchmark-utils-benchmark", "compose/benchmark-utils/benchmark", [BuildType.COMPOSE])
-includeProject(":compose:compiler:compiler", [BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":compose:compiler:compiler", [BuildType.COMPOSE])
 includeProject(":compose:compiler:compiler:integration-tests", [BuildType.COMPOSE])
-includeProject(":compose:compiler:compiler-hosted", [BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":compose:compiler:compiler-hosted", [BuildType.COMPOSE])
 includeProject(":compose:compiler:compiler-hosted:integration-tests", [BuildType.COMPOSE])
 includeProject(":compose:compiler:compiler-hosted:integration-tests:kotlin-compiler-repackaged", [BuildType.COMPOSE])
 includeProject(":compose:compiler:compiler-daemon", [BuildType.COMPOSE])
@@ -554,10 +567,10 @@
 includeProject(":compose:integration-tests:macrobenchmark", [BuildType.COMPOSE])
 includeProject(":compose:integration-tests:macrobenchmark-target", [BuildType.COMPOSE])
 includeProject(":compose:integration-tests:material-catalog", [BuildType.COMPOSE])
-includeProject(":compose:lint", [BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":compose:lint:internal-lint-checks", [BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":compose:lint:common", [BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":compose:lint:common-test", [BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":compose:lint", [BuildType.COMPOSE])
+includeProject(":compose:lint:internal-lint-checks", [BuildType.COMPOSE])
+includeProject(":compose:lint:common", [BuildType.COMPOSE])
+includeProject(":compose:lint:common-test", [BuildType.COMPOSE])
 includeProject(":compose:material", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3", [BuildType.COMPOSE])
 includeProject(":compose:material3:benchmark", [BuildType.COMPOSE])
@@ -584,9 +597,9 @@
 includeProject(":compose:material3:material3:integration-tests:material3-catalog", [BuildType.COMPOSE])
 includeProject(":compose:material:material:material-samples", "compose/material/material/samples", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3:material3-samples", "compose/material3/material3/samples", [BuildType.COMPOSE])
-includeProject(":compose:runtime", [BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":compose:runtime:runtime", [BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":compose:runtime:runtime-lint", [BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":compose:runtime", [BuildType.COMPOSE])
+includeProject(":compose:runtime:runtime", [BuildType.COMPOSE])
+includeProject(":compose:runtime:runtime-lint", [BuildType.COMPOSE])
 includeProject(":compose:runtime:runtime-livedata", [BuildType.COMPOSE])
 includeProject(":compose:runtime:runtime-livedata:runtime-livedata-samples", "compose/runtime/runtime-livedata/samples", [BuildType.COMPOSE])
 includeProject(":compose:runtime:runtime-tracing", [BuildType.COMPOSE])
@@ -599,7 +612,7 @@
 includeProject(":compose:runtime:runtime-saveable:runtime-saveable-samples", "compose/runtime/runtime-saveable/samples", [BuildType.COMPOSE])
 includeProject(":compose:runtime:runtime:benchmark", "compose/runtime/runtime/compose-runtime-benchmark", [BuildType.COMPOSE])
 includeProject(":compose:runtime:runtime:integration-tests", [BuildType.COMPOSE])
-includeProject(":compose:runtime:runtime:runtime-samples", "compose/runtime/runtime/samples", [BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":compose:runtime:runtime:runtime-samples", "compose/runtime/runtime/samples", [BuildType.COMPOSE])
 includeProject(":compose:test-utils", [BuildType.COMPOSE])
 includeProject(":compose:ui", [BuildType.COMPOSE])
 includeProject(":compose:ui:ui", [BuildType.COMPOSE])
@@ -633,8 +646,8 @@
 includeProject(":compose:ui:ui-viewbinding:ui-viewbinding-samples", "compose/ui/ui-viewbinding/samples", [BuildType.COMPOSE])
 includeProject(":compose:ui:ui:integration-tests:ui-demos", [BuildType.COMPOSE])
 includeProject(":compose:ui:ui:ui-samples", "compose/ui/ui/samples", [BuildType.COMPOSE])
-includeProject(":concurrent:concurrent-futures", [BuildType.MAIN, BuildType.CAMERA, BuildType.COMPOSE])
-includeProject(":concurrent:concurrent-futures-ktx", [BuildType.MAIN, BuildType.CAMERA])
+includeProject(":concurrent:concurrent-futures", [BuildType.MAIN, BuildType.COMPOSE])
+includeProject(":concurrent:concurrent-futures-ktx", [BuildType.MAIN])
 includeProject(":constraintlayout:constraintlayout-compose", [BuildType.COMPOSE])
 includeProject(":constraintlayout:constraintlayout-compose-lint", [BuildType.COMPOSE])
 includeProject(":constraintlayout:constraintlayout-compose:integration-tests:demos", [BuildType.COMPOSE])
@@ -770,33 +783,33 @@
 includeProject(":lifecycle:integration-tests:incrementality", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:integration-tests:lifecycle-testapp", "lifecycle/integration-tests/testapp", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:integration-tests:lifecycle-testapp-kotlin", "lifecycle/integration-tests/kotlintestapp", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-common-java8", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-common-java8", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-compiler", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:lifecycle-extensions", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-livedata", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-livedata-core", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-livedata-core-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-livedata-core-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-livedata", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-livedata-core", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-livedata-core-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-livedata-core-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-livedata-core-truth", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-livedata-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-livedata-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-process", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:lifecycle-reactivestreams", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:lifecycle-reactivestreams-ktx", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-runtime-compose", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-runtime-compose:lifecycle-runtime-compose-samples", "lifecycle/lifecycle-runtime-compose/samples", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-runtime-compose:integration-tests:lifecycle-runtime-compose-demos", [BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-runtime-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-runtime-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-runtime-testing", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-runtime-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-runtime-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-runtime-testing", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-service", [BuildType.MAIN, BuildType.FLAN, BuildType.GLANCE])
-includeProject(":lifecycle:lifecycle-viewmodel", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-viewmodel", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-viewmodel-compose", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-viewmodel-compose:lifecycle-viewmodel-compose-samples", "lifecycle/lifecycle-viewmodel-compose/samples", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-viewmodel-compose:integration-tests:lifecycle-viewmodel-demos", [BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-viewmodel-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
-includeProject(":lifecycle:lifecycle-viewmodel-savedstate", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-viewmodel-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-viewmodel-savedstate", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
 includeProject(":lint-checks")
 includeProject(":lint-checks:integration-tests")
 includeProject(":loader:loader", [BuildType.MAIN])
@@ -1038,20 +1051,20 @@
 includeProject(":wear:watchface:watchface-style-old-api-test-stub", "wear/watchface/watchface-style/old-api-test-stub", [BuildType.MAIN, BuildType.WEAR])
 includeProject(":webkit:integration-tests:testapp", [BuildType.MAIN])
 includeProject(":webkit:webkit", [BuildType.MAIN])
-includeProject(":window:window", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:window-samples", "window/window/samples", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:extensions:extensions", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:extensions:core:core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:window-samples", "window/window/samples", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:extensions:extensions", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:extensions:core:core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
 includeProject(":window:integration-tests:configuration-change-tests", [BuildType.MAIN, BuildType.WINDOW])
-includeProject(":window:sidecar:sidecar", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:window-java", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:window-core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:sidecar:sidecar", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:window-java", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:window-core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
 includeProject(":window:window-rxjava2", [BuildType.MAIN, BuildType.WINDOW])
 includeProject(":window:window-rxjava3", [BuildType.MAIN, BuildType.WINDOW])
-includeProject(":window:window-demos:demo", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:window-demos:demo-common", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:window-demos:demo-second-app", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
-includeProject(":window:window-testing", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-demos:demo", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:window-demos:demo-common", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:window-demos:demo-second-app", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
+includeProject(":window:window-testing", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.WINDOW])
 includeProject(":work:integration-tests:testapp", [BuildType.MAIN])
 includeProject(":work:work-benchmark", [BuildType.MAIN])
 includeProject(":work:work-gcm", [BuildType.MAIN])
@@ -1103,7 +1116,7 @@
 
 includeProject(":internal-testutils-common", "testutils/testutils-common", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN])
 includeProject(":internal-testutils-datastore", "testutils/testutils-datastore", [BuildType.MAIN, BuildType.KMP])
-includeProject(":internal-testutils-runtime", "testutils/testutils-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.COMPOSE, BuildType.MEDIA, BuildType.WEAR, BuildType.CAMERA])
+includeProject(":internal-testutils-runtime", "testutils/testutils-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.COMPOSE, BuildType.MEDIA, BuildType.WEAR])
 includeProject(":internal-testutils-appcompat", "testutils/testutils-appcompat", [BuildType.MAIN])
 includeProject(":internal-testutils-espresso", "testutils/testutils-espresso", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":internal-testutils-fonts", "testutils/testutils-fonts", [BuildType.MAIN, BuildType.GLANCE, BuildType.MEDIA, BuildType.FLAN, BuildType.COMPOSE, BuildType.WEAR])
@@ -1171,6 +1184,10 @@
 // Workaround for b/203825166
 includeBuild("placeholder")
 
+// ---------------------------------------------------------------------
+// --- there should be no includeProject additions after this line -----
+// ---------------------------------------------------------------------
+
 // For a given project path add the transitive project references to the include set.
 void addReferences(String projectPath, Set<String> included) {
     if (projectPath in included) return
@@ -1179,11 +1196,33 @@
         addReferences(reference, included)
     }
 }
-Set<String> projectsToInclude = new HashSet<>()
-for (filteredProject in filteredProjects) {
-    addReferences(filteredProject, projectsToInclude)
+
+void includeRequestedProjectsAndDependencies() {
+    // Adding by including `:foo:bar` Gradle will automatically load `:foo`, so we need to
+    // add those implicit parent project references.
+    for (projectPath in projectReferences.keySet()) {
+        Set<String> newReferences = new HashSet<>()
+        for (reference in projectReferences[projectPath]) {
+            String[] segments = reference.substring(1).split(":")
+            String subpath = ""
+            for (int i = 0; i < segments.length; i++) {
+                subpath += ":" + segments[i]
+                if (allProjects.containsKey(subpath)) {
+                    newReferences.add(subpath)
+                }
+            }
+        }
+        projectReferences[projectPath].addAll(newReferences)
+    }
+
+    Set<String> projectsToInclude = new HashSet<>()
+    for (filteredProject in filteredProjects) {
+        addReferences(filteredProject, projectsToInclude)
+    }
+    for (entry in projectsToInclude) {
+        settings.include(entry)
+        project(entry).projectDir = allProjects[entry]
+    }
 }
-for (entry in projectsToInclude) {
-    settings.include(entry)
-    project(entry).projectDir = allProjects[entry]
-}
+
+includeRequestedProjectsAndDependencies()
diff --git a/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlExtensionImpl.kt b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlExtensionImpl.kt
new file mode 100644
index 0000000..fa45f3c
--- /dev/null
+++ b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlExtensionImpl.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.stableaidl
+
+import androidx.stableaidl.api.Action
+import androidx.stableaidl.api.StableAidlExtension
+import androidx.stableaidl.tasks.StableAidlCheckApi
+import androidx.stableaidl.tasks.UpdateStableAidlApiTask
+import com.android.build.api.variant.SourceDirectories
+import com.android.build.gradle.internal.tasks.factory.dependsOn
+import java.io.File
+import org.gradle.api.Task
+import org.gradle.api.tasks.TaskProvider
+
+/**
+ * Internal implementation of [StableAidlExtension] that wraps task providers.
+ */
+open class StableAidlExtensionImpl : StableAidlExtension {
+    override val checkAction: Action = object : Action {
+        override fun <T : Task> before(task: TaskProvider<T>) {
+            task.dependsOn(checkTaskProvider)
+        }
+    }
+
+    override val updateAction: Action = object : Action {
+        override fun <T : Task> before(task: TaskProvider<T>) {
+            task.dependsOn(updateTaskProvider)
+        }
+    }
+
+    override var taskGroup: String? = null
+        set(taskGroup) {
+            allTasks.forEach { (_, tasks) ->
+                tasks.forEach { task ->
+                    task.configure {
+                        it.group = taskGroup
+                    }
+                }
+            }
+            field = taskGroup
+        }
+
+    override fun addStaticImportDirs(vararg dirs: File) {
+        importSourceDirs.forEach { importSourceDir ->
+            dirs.forEach { dir ->
+                importSourceDir.addStaticSourceDirectory(dir.absolutePath)
+            }
+        }
+    }
+
+    internal lateinit var updateTaskProvider: TaskProvider<UpdateStableAidlApiTask>
+    internal lateinit var checkTaskProvider: TaskProvider<StableAidlCheckApi>
+
+    internal val importSourceDirs = mutableListOf<SourceDirectories.Flat>()
+    internal val allTasks = mutableMapOf<String, Set<TaskProvider<*>>>()
+}
diff --git a/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlPlugin.kt b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlPlugin.kt
index 91c809f..95a513e 100644
--- a/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlPlugin.kt
+++ b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/StableAidlPlugin.kt
@@ -16,6 +16,7 @@
 
 package androidx.stableaidl
 
+import androidx.stableaidl.api.StableAidlExtension
 import com.android.build.api.dsl.SdkComponents
 import com.android.build.api.variant.AndroidComponentsExtension
 import com.android.build.api.variant.DslExtension
@@ -29,6 +30,8 @@
 import org.gradle.api.file.RegularFile
 import org.gradle.api.provider.Provider
 
+private const val DEFAULT_VARIANT_NAME = "release"
+private const val EXTENSION_NAME = "stableaidl"
 private const val PLUGIN_DIRNAME = "stable_aidl"
 private const val GENERATED_PATH = "generated/source/$PLUGIN_DIRNAME"
 private const val INTERMEDIATES_PATH = "intermediates/${PLUGIN_DIRNAME}_parcelable"
@@ -40,6 +43,11 @@
         val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
             ?: throw GradleException("Stable AIDL plugin requires Android Gradle Plugin")
 
+        val extension = project.extensions.create(
+            EXTENSION_NAME,
+            StableAidlExtensionImpl::class.java
+        )
+
         // Obtain the AIDL executable and framework AIDL file paths using private APIs. See
         // b/268237729 for public API request, after which we can obtain them from SdkComponents.
         val base = project.extensions.getByType(BaseExtension::class.java)
@@ -130,7 +138,7 @@
                 lastReleasedApiDir,
                 generateAidlApiTask
             )
-            registerCheckAidlApi(
+            val checkAidlApiTask = registerCheckAidlApi(
                 project,
                 variant,
                 aidlExecutable,
@@ -141,12 +149,29 @@
                 generateAidlApiTask,
                 checkAidlApiReleaseTask
             )
-            registerUpdateAidlApi(
+            val updateAidlApiTask = registerUpdateAidlApi(
                 project,
                 variant,
                 lastCheckedInApiDir,
                 generateAidlApiTask
             )
+
+            if (variant.name == DEFAULT_VARIANT_NAME) {
+                extension.updateTaskProvider = updateAidlApiTask
+                extension.checkTaskProvider = checkAidlApiTask
+            }
+
+            extension.importSourceDirs.add(
+                variant.sources.getByName(SOURCE_TYPE_STABLE_AIDL_IMPORTS)
+            )
+
+            extension.allTasks[variant.name] = setOf(
+                compileAidlApiTask,
+                generateAidlApiTask,
+                checkAidlApiReleaseTask,
+                checkAidlApiTask,
+                updateAidlApiTask
+            )
         }
     }
 }
@@ -209,3 +234,19 @@
         }?.artifacts?.artifactFiles
     return listOfNotNull(aidlFiles, stableAidlFiles)
 }
+
+/**
+ * When the Stable AIDL plugin is applies to the project, runs the specified [lambda] with access to
+ * the plugin's public APIs via [StableAidlExtension].
+ *
+ * If the project does not have the Stable AIDL plugin applied, this is a no-op.
+ */
+fun Project.withStableAidlPlugin(lambda: (StableAidlExtension) -> Unit) {
+    project.plugins.withId("androidx.stableaidl") { plugin ->
+        (plugin as? StableAidlPlugin)?.let {
+            project.extensions.findByType(StableAidlExtension::class.java)?.let { ext ->
+                lambda(ext)
+            } ?: throw GradleException("Failed to locate extension for StableAidlPlugin")
+        } ?: throw GradleException("Plugin with ID \"androidx.stableaidl\" is not StableAidlPlugin")
+    }
+}
diff --git a/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/api/StableAidlExtension.kt b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/api/StableAidlExtension.kt
new file mode 100644
index 0000000..8c083ab
--- /dev/null
+++ b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/api/StableAidlExtension.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.stableaidl.api
+
+import java.io.File
+import org.gradle.api.Incubating
+import org.gradle.api.Task
+import org.gradle.api.tasks.TaskProvider
+
+/**
+ * Extension that allows access to the StableAidl plugin's public APIs.
+ */
+interface StableAidlExtension {
+    /**
+     * An action representing the task that checks the current Stable AIDL API surface for
+     * compatibility against the previously-frozen API surface.
+     */
+    @get:Incubating
+    val checkAction: Action
+
+    /**
+     * An action representing the task that updates the frozen Stable AIDL API surface.
+     */
+    @get:Incubating
+    val updateAction: Action
+
+    /**
+     * The task group to use for Stable AIDL tasks, or `null` to hide them.
+     */
+    @get:Incubating
+    var taskGroup: String?
+
+    /**
+     * Adds static import directories to be passed to Stable AIDL.
+     *
+     * Static imports may be used in `import` statements, but are not exported to dependencies.
+     */
+    fun addStaticImportDirs(vararg dirs: File)
+}
+
+interface Action {
+    /**
+     * Runs the action before the specified [task].
+     */
+    fun <T : Task> before(task: TaskProvider<T>)
+}
diff --git a/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/tasks/StableAidlPackageApi.kt b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/tasks/StableAidlPackageApi.kt
index 218b300..370dd6d 100644
--- a/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/tasks/StableAidlPackageApi.kt
+++ b/stableaidl/stableaidl-gradle-plugin/src/main/java/androidx/stableaidl/tasks/StableAidlPackageApi.kt
@@ -31,10 +31,12 @@
 import org.gradle.api.tasks.PathSensitive
 import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.TaskAction
+import org.gradle.work.DisableCachingByDefault
 
 /**
  * Transforms an AAR by adding parcelable headers.
  */
+@DisableCachingByDefault(because = "Primarily filesystem operations")
 abstract class StableAidlPackageApi : DefaultTask() {
     @get:InputFile
     @get:PathSensitive(PathSensitivity.RELATIVE)
diff --git a/test/screenshot/screenshot/build.gradle b/test/screenshot/screenshot/build.gradle
index aef8ffc..7147d25 100644
--- a/test/screenshot/screenshot/build.gradle
+++ b/test/screenshot/screenshot/build.gradle
@@ -30,10 +30,7 @@
 )
 
 dependencies {
-    bundleInside(project(
-            path: ":test:screenshot:screenshot-proto",
-            configuration: "export"
-    ))
+    bundleInside(project(path: ":test:screenshot:screenshot-proto", configuration: "export"))
     implementation("androidx.annotation:annotation:1.0.0")
     implementation("androidx.core:core:1.5.0-rc02")
 
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
index c0384d2..c91c791 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
@@ -102,7 +102,7 @@
         // Short click with a time duration as a parameter (`click(long duration)`).
         UiObject2 button4 = mDevice.findObject(By.res(TEST_APP, "button4"));
         assertEquals("text4", button4.getText());
-        button4.click((long) (ViewConfiguration.getLongPressTimeout() / 1.5));
+        button4.click(50L);
         button4.wait(Until.textEquals("text4_clicked"), TIMEOUT_MS);
         assertEquals("text4_clicked", button4.getText());
 
@@ -121,8 +121,7 @@
         // Short click with two parameters (`click(Point point, long duration)`).
         UiObject2 button6 = mDevice.findObject(By.res(TEST_APP, "button6"));
         assertEquals("text6", button6.getText());
-        button6.click(getPointInsideBounds(button6),
-                (long) (ViewConfiguration.getLongPressTimeout() / 1.5));
+        button6.click(getPointInsideBounds(button6), 50L);
         button6.wait(Until.textEquals("text6_clicked"), TIMEOUT_MS);
         assertEquals("text6_clicked", button6.getText());
 
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/By.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/By.java
index 9c10f1f..d480917 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/By.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/By.java
@@ -328,8 +328,8 @@
      * @see BySelector#hasAncestor(BySelector, int)
      */
     public static @NonNull BySelector hasAncestor(@NonNull BySelector ancestorSelector,
-            @IntRange(from = 1) int maxHeight) {
-        return new BySelector().hasAncestor(ancestorSelector, maxHeight);
+            @IntRange(from = 1) int maxAncestorDistance) {
+        return new BySelector().hasAncestor(ancestorSelector, maxAncestorDistance);
     }
 
     /**
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/ByMatcher.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/ByMatcher.java
index f653171..9ad57c2 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/ByMatcher.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/ByMatcher.java
@@ -59,14 +59,14 @@
 
     // Inverts parent-child relationships until a root selector is found.
     private BySelector invertSelector(BySelector selector) {
-        if (selector.mParentSelector == null) {
+        if (selector.mAncestorSelector == null) {
             return selector;
         }
-        BySelector parent = new BySelector(selector.mParentSelector);
-        selector.mParentSelector = null;
-        selector.mMaxDepth = selector.mParentHeight;
-        selector.mParentHeight = null;
-        return invertSelector(parent.hasDescendant(selector));
+        BySelector ancestor = new BySelector(selector.mAncestorSelector);
+        selector.mAncestorSelector = null;
+        selector.mMaxDepth = selector.mMaxAncestorDistance;
+        selector.mMaxAncestorDistance = null;
+        return invertSelector(ancestor.hasDescendant(selector));
     }
 
     /**
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/BySelector.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/BySelector.java
index c6997db..63a0a49 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/BySelector.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/BySelector.java
@@ -51,9 +51,9 @@
     Integer mMinDepth;
     Integer mMaxDepth;
 
-    // Parent selector
-    BySelector mParentSelector;
-    Integer mParentHeight;
+    // Ancestor selector
+    BySelector mAncestorSelector;
+    Integer mMaxAncestorDistance;
 
     // Child selectors
     final List<BySelector> mChildSelectors = new LinkedList<>();
@@ -87,9 +87,9 @@
         mMinDepth = original.mMinDepth;
         mMaxDepth = original.mMaxDepth;
 
-        mParentSelector = original.mParentSelector == null ? null :
-                new BySelector(original.mParentSelector);
-        mParentHeight = original.mParentHeight;
+        mAncestorSelector = original.mAncestorSelector == null ? null :
+                new BySelector(original.mAncestorSelector);
+        mMaxAncestorDistance = original.mMaxAncestorDistance;
 
         for (BySelector childSelector : original.mChildSelectors) {
             mChildSelectors.add(new BySelector(childSelector));
@@ -595,10 +595,10 @@
      */
     public @NonNull BySelector hasAncestor(@NonNull BySelector ancestorSelector) {
         checkNotNull(ancestorSelector, "ancestorSelector cannot be null");
-        if (mParentSelector != null) {
+        if (mAncestorSelector != null) {
             throw new IllegalStateException("Parent/ancestor selector is already defined");
         }
-        mParentSelector = ancestorSelector;
+        mAncestorSelector = ancestorSelector;
         return this;
     }
 
@@ -607,14 +607,16 @@
      * it has an ancestor element which matches the {@code ancestorSelector} and all other
      * criteria for this selector are met.
      *
-     * @param ancestorSelector The selector used to find a matching ancestor element.
-     * @param maxHeight        The maximum height above the element to search for the ancestor.
+     * @param ancestorSelector    The selector used to find a matching ancestor element.
+     * @param maxAncestorDistance The maximum distance between the element and its relevant
+     *                            ancestor in the view hierarchy, e.g. 1 only matches the parent
+     *                            element, 2 matches parent or grandparent.
      * @return A reference to this {@link BySelector}.
      */
     public @NonNull BySelector hasAncestor(@NonNull BySelector ancestorSelector,
-            @IntRange(from = 1) int maxHeight) {
+            @IntRange(from = 1) int maxAncestorDistance) {
         hasAncestor(ancestorSelector);
-        mParentHeight = maxHeight;
+        mMaxAncestorDistance = maxAncestorDistance;
         return this;
     }
 
@@ -626,7 +628,7 @@
      *
      * @param childSelector The selector used to find a matching child element.
      * @return A reference to this {@link BySelector}.
-     * @throws IllegalArgumentException if the selector has a parent selector
+     * @throws IllegalArgumentException if the selector has a parent/ancestor selector
      */
     public @NonNull BySelector hasChild(@NonNull BySelector childSelector) {
         checkNotNull(childSelector, "childSelector cannot be null");
@@ -641,11 +643,11 @@
      *
      * @param descendantSelector The selector used to find a matching descendant element.
      * @return A reference to this {@link BySelector}.
-     * @throws IllegalArgumentException if the selector has a parent selector
+     * @throws IllegalArgumentException if the selector has a parent/ancestor selector
      */
     public @NonNull BySelector hasDescendant(@NonNull BySelector descendantSelector) {
         checkNotNull(descendantSelector, "descendantSelector cannot be null");
-        if (descendantSelector.mParentSelector != null) {
+        if (descendantSelector.mAncestorSelector != null) {
             // Search root is ambiguous with nested parent selectors.
             throw new IllegalArgumentException(
                     "Nested parent/ancestor selectors are not supported");
@@ -663,7 +665,7 @@
      * @param descendantSelector The selector used to find a matching descendant element.
      * @param maxDepth The maximum depth under the element to search the descendant.
      * @return A reference to this {@link BySelector}.
-     * @throws IllegalArgumentException if the selector has a parent selector
+     * @throws IllegalArgumentException if the selector has a parent/ancestor selector
      */
     public @NonNull BySelector hasDescendant(@NonNull BySelector descendantSelector, int maxDepth) {
         hasDescendant(descendantSelector);
@@ -721,9 +723,9 @@
         if (mSelected != null) {
             builder.append("SELECTED='").append(mSelected).append("', ");
         }
-        if (mParentSelector != null) {
-            builder.append("PARENT='")
-                    .append(mParentSelector.toString().substring(11))
+        if (mAncestorSelector != null) {
+            builder.append("ANCESTOR='")
+                    .append(mAncestorSelector.toString().substring(11))
                     .append("', ");
         }
         for (BySelector childSelector : mChildSelectors) {
@@ -741,4 +743,3 @@
         return value;
     }
 }
-
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java
index 8c8a203..1c165d3 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java
@@ -146,8 +146,8 @@
 
         // Loop
         MotionEvent event;
-        for (long elapsedTime = 0; !pending.isEmpty() || !active.isEmpty();
-                elapsedTime = SystemClock.uptimeMillis() - startTime) {
+        long elapsedTime = 0;
+        for (; !pending.isEmpty() || !active.isEmpty(); elapsedTime += injectionDelay) {
 
             // Touch up any completed pointers
             while (!active.isEmpty()
@@ -168,7 +168,7 @@
                     action = MotionEvent.ACTION_POINTER_UP
                             + (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
                 }
-                event = getMotionEvent(startTime, startTime + elapsedTime, action, properties,
+                event = getMotionEvent(startTime, SystemClock.uptimeMillis(), action, properties,
                         coordinates, gesture.displayId());
                 getDevice().getUiAutomation().injectInputEvent(event, false);
 
@@ -183,8 +183,9 @@
 
             }
             if (!active.isEmpty()) {
-                event = getMotionEvent(startTime, startTime + elapsedTime, MotionEvent.ACTION_MOVE,
-                        properties, coordinates, active.peek().displayId());
+                event = getMotionEvent(startTime, SystemClock.uptimeMillis(),
+                        MotionEvent.ACTION_MOVE, properties, coordinates,
+                        active.peek().displayId());
                 getDevice().getUiAutomation().injectInputEvent(event, false);
             }
 
@@ -205,7 +206,7 @@
                     action = MotionEvent.ACTION_POINTER_DOWN
                             + ((properties.size() - 1) << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
                 }
-                event = getMotionEvent(startTime, startTime + elapsedTime, action, properties,
+                event = getMotionEvent(startTime, SystemClock.uptimeMillis(), action, properties,
                         coordinates, gesture.displayId());
                 getDevice().getUiAutomation().injectInputEvent(event, false);
 
@@ -215,6 +216,12 @@
 
             SystemClock.sleep(injectionDelay);
         }
+
+        long upTime = SystemClock.uptimeMillis() - startTime;
+        if (upTime >= 2 * elapsedTime) {
+            Log.w(TAG, String.format("Gestures took longer than expected (%dms >> %dms), device "
+                    + "might be in a busy state.", upTime, elapsedTime));
+        }
     }
 
     /** Helper function to obtain a MotionEvent. */
diff --git a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/Card.kt b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/Card.kt
index c517d99..332cf06 100644
--- a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/Card.kt
+++ b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/Card.kt
@@ -17,7 +17,7 @@
 package androidx.tv.integration.playground
 
 import androidx.compose.foundation.background
-import androidx.compose.foundation.focusable
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.width
@@ -37,6 +37,6 @@
             .width(200.dp)
             .height(150.dp)
             .drawBorderOnFocus()
-            .focusable()
+            .clickable { }
     )
 }
\ No newline at end of file
diff --git a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt
index 64f92b9..6f6d535 100644
--- a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt
+++ b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt
@@ -16,7 +16,6 @@
 
 package androidx.tv.integration.playground
 
-import androidx.compose.animation.ExperimentalAnimationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.focusable
@@ -42,8 +41,9 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
-import androidx.tv.foundation.ExperimentalTvFoundationApi
 import androidx.tv.material3.Carousel
 import androidx.tv.material3.CarouselDefaults
 import androidx.tv.material3.CarouselState
@@ -88,9 +88,7 @@
     }
 }
 
-@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalAnimationApi::class,
-    ExperimentalTvFoundationApi::class
-)
+@OptIn(ExperimentalTvMaterial3Api::class)
 @Composable
 internal fun FeaturedCarousel(modifier: Modifier = Modifier) {
     val backgrounds = listOf(
@@ -105,41 +103,47 @@
     )
 
     val carouselState = remember { CarouselState() }
-    FocusGroup {
-        Carousel(
-            itemCount = backgrounds.size,
-            carouselState = carouselState,
-            modifier = modifier
-                .height(300.dp)
-                .fillMaxWidth(),
-            carouselIndicator = {
-                CarouselDefaults.IndicatorRow(
-                    itemCount = backgrounds.size,
-                    activeItemIndex = carouselState.activeItemIndex,
+    Carousel(
+        itemCount = backgrounds.size,
+        carouselState = carouselState,
+        modifier = modifier
+            .height(300.dp)
+            .fillMaxWidth(),
+        carouselIndicator = {
+            CarouselDefaults.IndicatorRow(
+                itemCount = backgrounds.size,
+                activeItemIndex = carouselState.activeItemIndex,
+                modifier = Modifier
+                    .align(Alignment.BottomEnd)
+                    .padding(16.dp),
+            )
+        }
+    ) { itemIndex ->
+        CarouselItem(
+            modifier = Modifier.semantics {
+                contentDescription = "Featured Content"
+            },
+            background = {
+                Box(
                     modifier = Modifier
-                        .align(Alignment.BottomEnd)
-                        .padding(16.dp),
+                        .background(backgrounds[itemIndex])
+                        .fillMaxSize()
                 )
-            }
-        ) { itemIndex ->
-            CarouselItem(
-                background = {
-                    Box(
-                        modifier = Modifier
-                            .background(backgrounds[itemIndex])
-                            .fillMaxSize()
-                    )
-                },
-                modifier =
-                if (itemIndex == 0)
-                    Modifier.initiallyFocused()
-                else
-                    Modifier.restorableFocus()
+            },
+        ) {
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .padding(20.dp),
+                contentAlignment = Alignment.BottomStart
             ) {
-                Box(modifier = Modifier) {
-                    OverlayButton(
-                        modifier = Modifier
-                    )
+                Column {
+                    Text(text = "This is sample text content.", color = Color.Yellow)
+                    Text(text = "Sample description.", color = Color.Yellow)
+                    Row {
+                        OverlayButton(text = "Play")
+                        OverlayButton(text = "Add to Watchlist")
+                    }
                 }
             }
         }
@@ -147,14 +151,16 @@
 }
 
 @Composable
-private fun OverlayButton(modifier: Modifier = Modifier) {
+private fun OverlayButton(modifier: Modifier = Modifier, text: String = "Play") {
     var isFocused by remember { mutableStateOf(false) }
 
     Button(
         onClick = { },
         modifier = modifier
-            .onFocusChanged { isFocused = it.isFocused }
-            .padding(40.dp)
+            .onFocusChanged {
+                isFocused = it.isFocused
+            }
+            .padding(20.dp)
             .border(
                 width = 2.dp,
                 color = if (isFocused) Color.Red else Color.Transparent,
@@ -162,6 +168,6 @@
             )
             .padding(vertical = 2.dp, horizontal = 5.dp)
     ) {
-        Text(text = "Play")
+        Text(text = text)
     }
 }
diff --git a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/ImmersiveList.kt b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/ImmersiveList.kt
index b8ed37f..ac3d021 100644
--- a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/ImmersiveList.kt
+++ b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/ImmersiveList.kt
@@ -16,24 +16,19 @@
 
 package androidx.tv.integration.playground
 
-import android.util.Log
 import androidx.compose.foundation.background
-import androidx.compose.foundation.border
-import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.semantics.CollectionItemInfo
+import androidx.compose.ui.semantics.collectionItemInfo
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.ExperimentalTvFoundationApi
 import androidx.tv.foundation.lazy.list.TvLazyColumn
@@ -54,7 +49,6 @@
 private fun SampleImmersiveList() {
     val immersiveListHeight = 300.dp
     val cardSpacing = 10.dp
-    val cardWidth = 200.dp
     val cardHeight = 150.dp
     val backgrounds = listOf(
         Color.Red,
@@ -76,27 +70,24 @@
                 )
             }
         ) {
-            Row(horizontalArrangement = Arrangement.spacedBy(cardSpacing)) {
-                backgrounds.forEachIndexed { index, backgroundColor ->
-                    var isFocused by remember { mutableStateOf(false) }
+            LazyRow(
+                horizontalArrangement = Arrangement.spacedBy(cardSpacing),
+                modifier = Modifier.lazyListSemantics(1, backgrounds.count())
+            ) {
+                itemsIndexed(backgrounds) { index, backgroundColor ->
+                    val cardModifier =
+                        if (index == 0)
+                            Modifier.initiallyFocused()
+                        else
+                            Modifier.restorableFocus()
 
-                    Box(
-                        modifier = Modifier
-                            .background(backgroundColor)
-                            .width(cardWidth)
-                            .height(cardHeight)
-                            .border(5.dp, Color.White.copy(alpha = if (isFocused) 1f else 0.3f))
-                            .then(
-                                if (index == 0)
-                                    Modifier.initiallyFocused()
-                                else
-                                    Modifier.restorableFocus()
-                            )
-                            .onFocusChanged { isFocused = it.isFocused }
-                            .immersiveListItem(index)
-                            .clickable {
-                                Log.d("ImmersiveList", "Item $index was clicked")
+                    Card(
+                        modifier = cardModifier
+                            .semantics {
+                                collectionItemInfo = CollectionItemInfo(0, 1, index, 1)
                             }
+                            .immersiveListItem(index),
+                        backgroundColor = backgroundColor
                     )
                 }
             }
diff --git a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/LazyRowsAndColumns.kt b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/LazyRowsAndColumns.kt
index 7ecfec8..2fbddf4 100644
--- a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/LazyRowsAndColumns.kt
+++ b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/LazyRowsAndColumns.kt
@@ -25,11 +25,17 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.semantics.CollectionInfo
+import androidx.compose.ui.semantics.CollectionItemInfo
+import androidx.compose.ui.semantics.collectionInfo
+import androidx.compose.ui.semantics.collectionItemInfo
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.ExperimentalTvFoundationApi
 import androidx.tv.foundation.PivotOffsets
 import androidx.tv.foundation.lazy.list.TvLazyColumn
 import androidx.tv.foundation.lazy.list.TvLazyRow
+import androidx.tv.foundation.lazy.list.itemsIndexed
 
 const val rowsCount = 20
 const val columnsCount = 100
@@ -58,19 +64,35 @@
     val backgroundColors = List(columnsCount) { colors.random() }
 
     FocusGroup {
-        TvLazyRow(modifier, horizontalArrangement = Arrangement.spacedBy(10.dp)) {
-            backgroundColors.forEachIndexed { index, backgroundColor ->
-                item {
-                    Card(
-                        backgroundColor = backgroundColor,
-                        modifier =
-                        if (index == 0)
-                            Modifier.initiallyFocused()
-                        else
-                            Modifier.restorableFocus()
-                    )
-                }
+        TvLazyRow(
+            modifier = modifier.lazyListSemantics(1, columnsCount),
+            horizontalArrangement = Arrangement.spacedBy(10.dp)
+        ) {
+            itemsIndexed(backgroundColors) { index, item ->
+                val cardModifier =
+                    if (index == 0)
+                        Modifier.initiallyFocused()
+                    else
+                        Modifier.restorableFocus()
+
+                Card(
+                    modifier = cardModifier.semantics {
+                        collectionItemInfo = CollectionItemInfo(0, 1, index, 1)
+                    },
+                    backgroundColor = item
+                )
             }
         }
     }
 }
+
+@Composable
+fun Modifier.lazyListSemantics(rowCount: Int = -1, columnCount: Int = -1): Modifier {
+    return this.then(
+        remember(rowCount, columnCount) {
+            Modifier.semantics {
+                collectionInfo = CollectionInfo(rowCount, columnCount)
+            }
+        }
+    )
+}
diff --git a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/NavigationDrawer.kt b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/NavigationDrawer.kt
index 86865b3..1257c1b 100644
--- a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/NavigationDrawer.kt
+++ b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/NavigationDrawer.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -28,11 +29,11 @@
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.selection.selectableGroup
+import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.KeyboardArrowLeft
 import androidx.compose.material.icons.filled.KeyboardArrowRight
-import androidx.compose.material3.Button
-import androidx.compose.material3.ButtonDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
@@ -43,14 +44,16 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.semantics.selected
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.zIndex
-import androidx.tv.foundation.ExperimentalTvFoundationApi
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Icon
@@ -110,7 +113,7 @@
     }
 }
 
-@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalTvFoundationApi::class)
+@OptIn(ExperimentalTvMaterial3Api::class)
 @Composable
 private fun Sidebar(
     drawerValue: DrawerValue,
@@ -128,8 +131,10 @@
     Column(
         modifier = Modifier
             .fillMaxHeight()
-            .background(pageColor),
+            .background(pageColor)
+            .selectableGroup(),
         horizontalAlignment = Alignment.CenterHorizontally,
+        verticalArrangement = Arrangement.spacedBy(10.dp)
     ) {
         NavigationItem(
             imageVector = Icons.Default.KeyboardArrowRight,
@@ -160,15 +165,19 @@
 ) {
     var isFocused by remember { mutableStateOf(false) }
 
-    Button(
-        onClick = { selectedIndex.value = index },
+    Box(
         modifier = modifier
-            .onFocusChanged { isFocused = it.isFocused },
-        colors = ButtonDefaults.filledTonalButtonColors(
-            containerColor = if (isFocused) Color.White else Color.Transparent,
-        )
+            .clip(RoundedCornerShape(10.dp))
+            .onFocusChanged { isFocused = it.isFocused }
+            .background(if (isFocused) Color.White else Color.Transparent)
+            .semantics(mergeDescendants = true) {
+                selected = selectedIndex.value == index
+            }
+            .clickable {
+                selectedIndex.value = index
+            }
     ) {
-        Box(modifier = Modifier) {
+        Box(modifier = Modifier.padding(10.dp)) {
             Row(
                 verticalAlignment = Alignment.CenterVertically,
                 horizontalArrangement = Arrangement.spacedBy(5.dp),
diff --git a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt
index 51f87fd..afc1361 100644
--- a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt
@@ -1489,15 +1489,24 @@
                 userScrollEnabled = false,
             ) {
                 items(5) {
-                    Spacer(Modifier.size(itemSize).testTag("$it"))
+                    Box(
+                        modifier = Modifier
+                            .size(itemSize)
+                            .border(2.dp, Color.Blue)
+                            .testTag("$it")
+                            .focusable()
+                    ) {
+                        BasicText("$it")
+                    }
                 }
             }
         }
 
-        rule.keyPress(1)
+        rule.onNodeWithTag("2").performSemanticsAction(SemanticsActions.RequestFocus)
+        rule.keyPress(2)
 
-        rule.onNodeWithTag("1")
-            .assertStartPositionInRootIsEqualTo(itemSize)
+        rule.onNodeWithTag("1").assertIsDisplayed()
+        rule.onNodeWithTag("3").assertIsNotDisplayed()
     }
 
     @Test
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/ContentInViewModifier.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/ContentInViewModifier.kt
index 6c22786..716e8f8 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/ContentInViewModifier.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/ContentInViewModifier.kt
@@ -59,7 +59,8 @@
     private val orientation: Orientation,
     private val scrollState: ScrollableState,
     private val reverseDirection: Boolean,
-    private val pivotOffsets: PivotOffsets
+    private val pivotOffsets: PivotOffsets,
+    private val userScrollEnabled: Boolean
 ) : BringIntoViewResponder,
     OnRemeasuredModifier,
     OnPlacedModifier {
@@ -352,6 +353,8 @@
         trailingEdgeOfItemRequestingFocus: Float,
         containerSize: Float
     ): Float {
+        if (!userScrollEnabled) return 0f
+
         val sizeOfItemRequestingFocus =
             abs(trailingEdgeOfItemRequestingFocus - leadingEdgeOfItemRequestingFocus)
         val childSmallerThanParent = sizeOfItemRequestingFocus <= containerSize
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt
index 635441e..f7f95a3 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt
@@ -79,9 +79,15 @@
     factory = {
         val coroutineScope = rememberCoroutineScope()
         val keepFocusedChildInViewModifier =
-            remember(coroutineScope, orientation, state, reverseDirection, pivotOffsets) {
+            remember(coroutineScope, orientation, state, reverseDirection, pivotOffsets, enabled) {
                 ContentInViewModifier(
-                    coroutineScope, orientation, state, reverseDirection, pivotOffsets)
+                    scope = coroutineScope,
+                    orientation = orientation,
+                    scrollState = state,
+                    reverseDirection = reverseDirection,
+                    pivotOffsets = pivotOffsets,
+                    userScrollEnabled = enabled
+                )
             }
 
         Modifier
diff --git a/tv/tv-material/api/public_plus_experimental_current.txt b/tv/tv-material/api/public_plus_experimental_current.txt
index bebfaef..e2cc7d6 100644
--- a/tv/tv-material/api/public_plus_experimental_current.txt
+++ b/tv/tv-material/api/public_plus_experimental_current.txt
@@ -410,6 +410,18 @@
     field public static final androidx.tv.material3.OutlinedIconButtonDefaults INSTANCE;
   }
 
+  @androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class RadioButtonColors {
+  }
+
+  @androidx.tv.material3.ExperimentalTvMaterial3Api public final class RadioButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.tv.material3.RadioButtonColors colors(optional long selectedColor, optional long unselectedColor, optional long disabledSelectedColor, optional long disabledUnselectedColor);
+    field public static final androidx.tv.material3.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.tv.material3.RadioButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
   @androidx.tv.material3.ExperimentalTvMaterial3Api public sealed interface ScrollPauseHandle {
     method public void resumeAutoScroll();
   }
@@ -450,6 +462,20 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> LocalAbsoluteTonalElevation;
   }
 
+  @androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class SwitchColors {
+  }
+
+  @androidx.tv.material3.ExperimentalTvMaterial3Api public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.tv.material3.SwitchColors colors(optional long checkedThumbColor, optional long checkedTrackColor, optional long checkedBorderColor, optional long checkedIconColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedBorderColor, optional long uncheckedIconColor, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledCheckedBorderColor, optional long disabledCheckedIconColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor, optional long disabledUncheckedBorderColor, optional long disabledUncheckedIconColor);
+    method public float getIconSize();
+    property public final float IconSize;
+    field public static final androidx.tv.material3.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? thumbContent, optional boolean enabled, optional androidx.tv.material3.SwitchColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
   @androidx.tv.material3.ExperimentalTvMaterial3Api public final class TabColors {
   }
 
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselScopeTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselScopeTest.kt
index 10080e0..2f80311 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselScopeTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselScopeTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.tv.material3
 
-import androidx.compose.animation.ExperimentalAnimationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.focusable
@@ -50,7 +49,7 @@
     @get:Rule
     val rule = createComposeRule()
 
-    @OptIn(ExperimentalTvMaterial3Api::class, ExperimentalAnimationApi::class)
+    @OptIn(ExperimentalTvMaterial3Api::class)
     @Test
     fun carouselItem_parentContainerGainsFocused_onBackPress() {
         val containerBoxTag = "container-box"
@@ -69,7 +68,8 @@
             ) {
                 CarouselScope(carouselState = carouselState)
                     .CarouselItem(
-                        modifier = Modifier.testTag(carouselItemTag),
+                        modifier = Modifier
+                            .testTag(carouselItemTag),
                         background = {
                             Box(
                                 modifier = Modifier
@@ -87,7 +87,8 @@
         rule.waitForIdle()
 
         // Check if overlay button in carousel item is focused
-        rule.onNodeWithTag(sampleButtonTag).assertIsFocused()
+        rule.onNodeWithTag(sampleButtonTag, useUnmergedTree = true)
+            .assertIsFocused()
 
         // Trigger back press
         performKeyPress(NativeKeyEvent.KEYCODE_BACK)
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt
index 7582b2c..1c863ef 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt
@@ -67,6 +67,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth.assertThat
+import kotlin.math.abs
 import kotlinx.coroutines.delay
 import org.junit.Rule
 import org.junit.Test
@@ -275,7 +276,6 @@
         rule.onNodeWithText("Text 2").assertIsDisplayed()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
     fun carousel_pagerIndicatorDisplayed() {
         rule.setContent {
@@ -287,7 +287,6 @@
         rule.onNodeWithTag("indicator").assertIsDisplayed()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
     fun carousel_withAnimatedContent_successfulTransition() {
         rule.setContent {
@@ -308,7 +307,6 @@
         rule.onNodeWithText("PLAY").assertIsDisplayed()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
     fun carousel_withAnimatedContent_successfulFocusIn() {
         rule.setContent {
@@ -326,8 +324,9 @@
         rule.mainClock.advanceTimeBy(animationTime, false)
         rule.mainClock.advanceTimeByFrame()
 
-        rule.onNodeWithText("Play 0").assertIsDisplayed()
-        rule.onNodeWithText("Play 0").assertIsFocused()
+        rule.onNodeWithText("Play 0", useUnmergedTree = true)
+            .assertIsDisplayed()
+            .assertIsFocused()
     }
 
     @Test
@@ -353,7 +352,7 @@
         rule.waitForIdle()
 
         // Check if the overlay button is focused
-        rule.onNodeWithText("Button-1").assertIsFocused()
+        rule.onNodeWithText("Button-1", useUnmergedTree = true).assertIsFocused()
 
         // Trigger back press event to exit focus
         performKeyPress(NativeKeyEvent.KEYCODE_BACK)
@@ -361,13 +360,12 @@
         rule.waitForIdle()
 
         // Check if carousel loses focus and parent container gains focus
-        rule.onNodeWithText("Button-1").assertIsNotFocused()
+        rule.onNodeWithText("Button-1", useUnmergedTree = true).assertIsNotFocused()
         rule.onNodeWithTag("box-container").assertIsFocused()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
-    fun carousel_withCarouselItem_parentContainerGainsFocus_onBackPress() {
+    fun carousel_withCarouselItem_parentContainerGainsFocusOnBackPress() {
         rule.setContent {
             Box(modifier = Modifier
                 .testTag("box-container")
@@ -391,7 +389,7 @@
         rule.waitForIdle()
 
         // Check if the overlay button is focused
-        rule.onNodeWithText("Play 0").assertIsFocused()
+        rule.onNodeWithText("Play 0", useUnmergedTree = true).assertIsFocused()
 
         // Trigger back press event to exit focus
         performKeyPress(NativeKeyEvent.KEYCODE_BACK)
@@ -399,11 +397,10 @@
         rule.waitForIdle()
 
         // Check if carousel loses focus and parent container gains focus
-        rule.onNodeWithText("Play 0").assertIsNotFocused()
+        rule.onNodeWithText("Play 0", useUnmergedTree = true).assertIsNotFocused()
         rule.onNodeWithTag("box-container").assertIsFocused()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
     fun carousel_scrollToRegainFocus_checkBringIntoView() {
         val focusRequester = FocusRequester()
@@ -491,7 +488,6 @@
         assertThat(checkNodeCompletelyVisible(rule, "featured-carousel")).isTrue()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
     fun carousel_zeroItemCount_shouldNotCrash() {
         val testTag = "emptyCarousel"
@@ -502,7 +498,6 @@
         rule.onNodeWithTag(testTag).assertExists()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
     fun carousel_oneItemCount_shouldNotCrash() {
         val testTag = "emptyCarousel"
@@ -514,7 +509,7 @@
     }
 
     @Test
-    fun carousel_manualScrolling_withFocusableItemsOnTop() {
+    fun carousel_manualScrollingWithFocusableItemsOnTop_focusStaysWithinCarousel() {
         rule.setContent {
             Column {
                 Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
@@ -551,8 +546,7 @@
 
         // Check that item 2 is in view and button 2 has focus
         rule.onNodeWithText("Button-2").assertIsDisplayed()
-        // TODO: Fix button 2 isn't gaining focus
-        // rule.onNodeWithText("Button-2").assertIsFocused()
+        rule.onNodeWithText("Button-2").assertIsFocused()
 
         // Check if the first focusable element in parent has focus
         rule.onNodeWithText("Row-button-1").assertIsNotFocused()
@@ -571,17 +565,24 @@
         rule.onNodeWithText("Button-1").assertIsFocused()
     }
 
-    @OptIn(ExperimentalAnimationApi::class)
     @Test
-    fun carousel_manualScrolling_fastMultipleKeyPresses() {
+    fun carousel_manualScrollingFastMultipleKeyPresses_focusStaysWithinCarousel() {
         val carouselState = CarouselState()
         val tabs = listOf("Tab 1", "Tab 2", "Tab 3")
+        var numberOfTimesTabGainedFocus = 0
 
         rule.setContent {
             var selectedTabIndex by remember { mutableStateOf(0) }
 
             Column {
-                TabRow(selectedTabIndex = selectedTabIndex) {
+                TabRow(
+                    modifier = Modifier.onFocusChanged {
+                        if (it.hasFocus || it.isFocused) {
+                            numberOfTimesTabGainedFocus++
+                        }
+                    },
+                    selectedTabIndex = selectedTabIndex
+                ) {
                     tabs.forEachIndexed { index, tab ->
                         Tab(
                             selected = index == selectedTabIndex,
@@ -599,33 +600,36 @@
         }
 
         rule.waitForIdle()
-        rule.onNodeWithTag("pager").performSemanticsAction(SemanticsActions.RequestFocus)
+        rule.onNodeWithText("Play 0").performSemanticsAction(SemanticsActions.RequestFocus)
         rule.waitForIdle()
 
         val itemProgression = listOf(6, 3, -4, 3, -6, 5, 3)
+        // reset the counter at test start.
+        numberOfTimesTabGainedFocus = 0
 
         itemProgression.forEach {
-            if (it < 0) {
-                performKeyPress(NativeKeyEvent.KEYCODE_DPAD_LEFT, it * -1)
-            } else {
-                performKeyPress(NativeKeyEvent.KEYCODE_DPAD_RIGHT, it)
-            }
+            performKeyPress(
+                if (it < 0) NativeKeyEvent.KEYCODE_DPAD_LEFT else NativeKeyEvent.KEYCODE_DPAD_RIGHT,
+                abs(it)
+            )
+            rule.waitForIdle()
         }
 
         rule.mainClock.advanceTimeBy(animationTime)
 
         val finalItem = itemProgression.sum()
-        rule.onNodeWithText("Play $finalItem").assertIsFocused()
+        assertThat(numberOfTimesTabGainedFocus).isEqualTo(0)
+        rule.onNodeWithText("Play $finalItem", useUnmergedTree = true).assertIsFocused()
 
         performKeyPress(NativeKeyEvent.KEYCODE_DPAD_RIGHT, 3)
 
         rule.mainClock.advanceTimeBy((animationTime) * 3)
 
-        rule.onNodeWithText("Play ${finalItem + 3}").assertIsFocused()
+        rule.onNodeWithText("Play ${finalItem + 3}", useUnmergedTree = true).assertIsFocused()
     }
 
     @Test
-    fun carousel_manualScrolling_onDpadLongPress() {
+    fun carousel_manualScrollingDpadLongPress_moveOnlyOneSlide() {
         rule.setContent {
             SampleCarousel(itemCount = 6) { index ->
                 SampleButton("Button ${index + 1}")
@@ -670,7 +674,7 @@
     }
 
     @Test
-    fun carousel_manualScrolling_ltr() {
+    fun carousel_manualScrollingLtr_RightMovesToNextSlideLeftMovesToPrevSlide() {
         rule.setContent {
             SampleCarousel { index ->
                 SampleButton("Button ${index + 1}")
@@ -716,7 +720,7 @@
     }
 
     @Test
-    fun carousel_manualScrolling_rtl() {
+    fun carousel_manualScrollingRtl_LeftMovesToNextSlideRightMovesToPrevSlide() {
         rule.setContent {
             CompositionLocalProvider(
                 LocalLayoutDirection provides LayoutDirection.Rtl
@@ -796,9 +800,30 @@
 
         rule.waitUntil(timeoutMillis = 5000) { itemChanges > minSuccessfulItemChanges }
     }
+
+    @Test
+    fun carousel_slideWithTwoButtonsInARow_focusMovesWithinSlideAndChangesSlideOnlyOnFocusExit() {
+        rule.setContent {
+            // No AutoScrolling
+            SampleCarousel(timeToDisplayItemMillis = Long.MAX_VALUE) {
+                Row {
+                    SampleButton("Left Button ${it + 1}")
+                    SampleButton("Right Button ${it + 1}")
+                }
+            }
+        }
+
+        rule.onNodeWithText("Left Button 1").performSemanticsAction(SemanticsActions.RequestFocus)
+        performKeyPress(KeyEvent.KEYCODE_DPAD_RIGHT)
+        // focus should have moved from left to right button
+        rule.onNodeWithText("Right Button 1").assertIsFocused()
+        performKeyPress(KeyEvent.KEYCODE_DPAD_RIGHT)
+        // slide should have changed.
+        rule.onNodeWithText("Left Button 2").assertIsFocused()
+    }
 }
 
-@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalAnimationApi::class)
+@OptIn(ExperimentalTvMaterial3Api::class)
 @Composable
 private fun SampleCarousel(
     carouselState: CarouselState = remember { CarouselState() },
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/RadioButtonScreenshotTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/RadioButtonScreenshotTest.kt
new file mode 100644
index 0000000..1ee4b70
--- /dev/null
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/RadioButtonScreenshotTest.kt
@@ -0,0 +1,162 @@
+/*
+ * 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.tv.material3
+
+import android.os.Build
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.input.InputMode
+import androidx.compose.ui.input.InputModeManager
+import androidx.compose.ui.platform.LocalInputModeManager
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performMouseInput
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@MediumTest
+@RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@OptIn(ExperimentalTestApi::class, ExperimentalTvMaterial3Api::class)
+class RadioButtonScreenshotTest(private val scheme: ColorSchemeWrapper) {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(TV_GOLDEN_MATERIAL3)
+
+    private val wrap = Modifier.wrapContentSize(Alignment.TopStart)
+    private val wrapperTestTag = "radioButtonWrapper"
+
+    @Test
+    fun radioButton_selected() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                RadioButton(selected = true, onClick = {})
+            }
+        }
+        assertSelectableAgainstGolden("radioButton_${scheme.name}_selected")
+    }
+
+    @Test
+    fun radioButton_notSelected() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                RadioButton(selected = false, onClick = {})
+            }
+        }
+        assertSelectableAgainstGolden("radioButton_${scheme.name}_notSelected")
+    }
+
+    @Test
+    fun radioButton_hovered() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                RadioButton(selected = false, onClick = {})
+            }
+        }
+        rule.onNodeWithTag(wrapperTestTag).performMouseInput {
+            enter(center)
+        }
+
+        assertSelectableAgainstGolden("radioButton_${scheme.name}_hovered")
+    }
+
+    @Test
+    fun radioButton_focused() {
+        val focusRequester = FocusRequester()
+        var localInputModeManager: InputModeManager? = null
+
+        rule.setMaterialContent(scheme.colorScheme) {
+            localInputModeManager = LocalInputModeManager.current
+            Box(wrap.testTag(wrapperTestTag)) {
+                RadioButton(
+                    selected = false,
+                    onClick = {},
+                    modifier = Modifier
+                        .focusRequester(focusRequester)
+                )
+            }
+        }
+
+        rule.runOnIdle {
+            @OptIn(ExperimentalComposeUiApi::class)
+            localInputModeManager!!.requestInputMode(InputMode.Keyboard)
+            focusRequester.requestFocus()
+        }
+
+        assertSelectableAgainstGolden("radioButton_${scheme.name}_focused")
+    }
+
+    @Test
+    fun radioButton_disabled_selected() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                RadioButton(selected = true, onClick = {}, enabled = false)
+            }
+        }
+        assertSelectableAgainstGolden("radioButton_${scheme.name}_disabled_selected")
+    }
+
+    @Test
+    fun radioButton_disabled_notSelected() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                RadioButton(selected = false, onClick = {}, enabled = false)
+            }
+        }
+        assertSelectableAgainstGolden("radioButton_${scheme.name}_disabled_notSelected")
+    }
+
+    private fun assertSelectableAgainstGolden(goldenName: String) {
+        rule.onNodeWithTag(wrapperTestTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenName)
+    }
+
+    // Provide the ColorScheme and their name parameter in a ColorSchemeWrapper.
+    // This makes sure that the default method name and the initial Scuba image generated
+    // name is as expected.
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun parameters() = arrayOf(
+            ColorSchemeWrapper("lightTheme", lightColorScheme()),
+            ColorSchemeWrapper("darkTheme", darkColorScheme()),
+        )
+    }
+
+    class ColorSchemeWrapper constructor(val name: String, val colorScheme: ColorScheme) {
+        override fun toString(): String {
+            return name
+        }
+    }
+}
\ No newline at end of file
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/RadioButtonTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/RadioButtonTest.kt
new file mode 100644
index 0000000..75cd25b
--- /dev/null
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/RadioButtonTest.kt
@@ -0,0 +1,218 @@
+/*
+ * 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.tv.material3
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.semantics.focused
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHasNoClickAction
+import androidx.compose.ui.test.assertIsNotSelected
+import androidx.compose.ui.test.assertIsSelected
+import androidx.compose.ui.test.isFocusable
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performClick
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalTvMaterial3Api::class)
+class RadioButtonTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val itemOne = "Bar"
+    private val itemTwo = "Foo"
+    private val itemThree = "Sap"
+
+    private fun SemanticsNodeInteraction.assertHasSelectedSemantics(): SemanticsNodeInteraction =
+        assertIsSelected()
+
+    private fun SemanticsNodeInteraction.assertHasUnSelectedSemantics(): SemanticsNodeInteraction =
+        assertIsNotSelected()
+
+    private val options = listOf(itemOne, itemTwo, itemThree)
+
+    @Test
+    fun radioGroupTest_defaultSemantics() {
+        val selected = mutableStateOf(itemOne)
+
+        rule.setContent {
+            LightMaterialTheme {
+                Column {
+                    options.forEach { item ->
+                        RadioButton(
+                            modifier = Modifier.testTag(item),
+                            selected = (selected.value == item),
+                            onClick = { selected.value = item }
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(itemOne)
+            .assert(
+                SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton)
+            )
+            .assertHasSelectedSemantics()
+        rule.onNodeWithTag(itemTwo)
+            .assertHasUnSelectedSemantics()
+            .assert(
+                SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton)
+            )
+        rule.onNodeWithTag(itemThree)
+            .assert(
+                SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton)
+            )
+            .assertHasUnSelectedSemantics()
+    }
+
+    @Test
+    fun radioGroupTest_ensureUnselectable() {
+        val selected = mutableStateOf(itemOne)
+
+        rule.setContent {
+            LightMaterialTheme {
+                Column {
+                    options.forEach { item ->
+                        RadioButton(
+                            modifier = Modifier.testTag(item),
+                            selected = (selected.value == item),
+                            onClick = { selected.value = item }
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(itemOne)
+            .assertHasSelectedSemantics()
+            .performClick()
+            .assertHasSelectedSemantics()
+
+        rule.onNodeWithTag(itemTwo)
+            .assertHasUnSelectedSemantics()
+
+        rule.onNodeWithTag(itemThree)
+            .assertHasUnSelectedSemantics()
+    }
+
+    @Test
+    fun radioGroupTest_clickSelect() {
+        val selected = mutableStateOf(itemOne)
+        rule.setContent {
+            LightMaterialTheme {
+                Column {
+                    options.forEach { item ->
+                        RadioButton(
+                            modifier = Modifier.testTag(item),
+                            selected = (selected.value == item),
+                            onClick = { selected.value = item }
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(itemTwo)
+            .assertHasUnSelectedSemantics()
+            .performClick()
+            .assertHasSelectedSemantics()
+
+        rule.onNodeWithTag(itemOne)
+            .assertHasUnSelectedSemantics()
+
+        rule.onNodeWithTag(itemThree)
+            .assertHasUnSelectedSemantics()
+    }
+
+    @Test
+    fun radioGroup_untoggleableAndMergeable_whenNullLambda() {
+        val parentTag = "parent"
+        rule.setContent {
+            LightMaterialTheme {
+                Column(
+                    Modifier
+                        .semantics(mergeDescendants = true) {}
+                        .testTag(parentTag)) {
+                    RadioButton(
+                        selected = true,
+                        onClick = null,
+                        modifier = Modifier.semantics { focused = true }
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag(parentTag)
+            .assertHasNoClickAction()
+            .assert(isFocusable()) // Check merged into parent
+    }
+
+    @Test
+    @LargeTest
+    fun radioGroupTest_clickSelectTwoDifferentItems() {
+        val selected = mutableStateOf(itemOne)
+
+        rule.setContent {
+            LightMaterialTheme {
+                Column {
+                    options.forEach { item ->
+                        RadioButton(
+                            modifier = Modifier.testTag(item),
+                            selected = (selected.value == item),
+                            onClick = { selected.value = item }
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(itemTwo)
+            .assertHasUnSelectedSemantics()
+            .performClick()
+            .assertHasSelectedSemantics()
+
+        rule.onNodeWithTag(itemOne)
+            .assertHasUnSelectedSemantics()
+
+        rule.onNodeWithTag(itemThree)
+            .assertHasUnSelectedSemantics()
+            .performClick()
+            .assertHasSelectedSemantics()
+
+        rule.onNodeWithTag(itemOne)
+            .assertHasUnSelectedSemantics()
+
+        rule.onNodeWithTag(itemTwo)
+            .assertHasUnSelectedSemantics()
+    }
+}
\ No newline at end of file
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/SwitchScreenshotTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/SwitchScreenshotTest.kt
new file mode 100644
index 0000000..dfa1fcf
--- /dev/null
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/SwitchScreenshotTest.kt
@@ -0,0 +1,273 @@
+/*
+ * 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.tv.material3
+
+import android.os.Build
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.InputMode
+import androidx.compose.ui.input.InputModeManager
+import androidx.compose.ui.platform.LocalInputModeManager
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.isToggleable
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performMouseInput
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@OptIn(ExperimentalTestApi::class, ExperimentalTvMaterial3Api::class)
+class SwitchScreenshotTest(private val scheme: ColorSchemeWrapper) {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(TV_GOLDEN_MATERIAL3)
+    private val wrapperTestTag = "switchWrapper"
+
+    private val wrapperModifier = Modifier
+        .wrapContentSize(Alignment.TopStart)
+        .testTag(wrapperTestTag)
+
+    @Test
+    fun switchTest_checked() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                Switch(checked = true, onCheckedChange = { })
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_checked")
+    }
+
+    @Test
+    fun switchTest_checked_rtl() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+                    Switch(checked = true, onCheckedChange = { })
+                }
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_checked_rtl")
+    }
+
+    @Test
+    fun switchTest_checked_customThumbColor() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                Switch(
+                    checked = true,
+                    onCheckedChange = { },
+                    colors = SwitchDefaults.colors(checkedThumbColor = Color.Green)
+                )
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_checked_customThumbColor")
+    }
+
+    @Test
+    fun switchTest_unchecked() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                Switch(checked = false, onCheckedChange = { })
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_unchecked")
+    }
+
+    @Test
+    fun switchTest_unchecked_rtl() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+                    Switch(checked = false, onCheckedChange = { })
+                }
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_unchecked_rtl")
+    }
+
+    @Test
+    fun switchTest_disabled_checked() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                Switch(checked = true, enabled = false, onCheckedChange = { })
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_disabled_checked")
+    }
+
+    @Test
+    fun switchTest_disabled_unchecked() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                Switch(checked = false, enabled = false, onCheckedChange = { })
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_disabled_unchecked")
+    }
+
+    @Test
+    fun switchTest_hover() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrapperModifier) {
+                Switch(
+                    checked = true,
+                    onCheckedChange = { }
+                )
+            }
+        }
+
+        rule.onNode(isToggleable())
+            .performMouseInput { enter(center) }
+
+        rule.waitForIdle()
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_hover")
+    }
+
+    @Test
+    fun switchTest_focus() {
+        val focusRequester = FocusRequester()
+        var localInputModeManager: InputModeManager? = null
+
+        rule.setMaterialContent(scheme.colorScheme) {
+            localInputModeManager = LocalInputModeManager.current
+            Box(wrapperModifier) {
+                Switch(
+                    checked = true,
+                    onCheckedChange = { },
+                    modifier = Modifier
+                        .testTag("switch")
+                        .focusRequester(focusRequester)
+                )
+            }
+        }
+
+        rule.runOnIdle {
+            @OptIn(ExperimentalComposeUiApi::class)
+            localInputModeManager!!.requestInputMode(InputMode.Keyboard)
+            focusRequester.requestFocus()
+        }
+
+        rule.waitForIdle()
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_focus")
+    }
+
+    @Test
+    fun switchTest_checked_icon() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            val icon: @Composable () -> Unit = {
+                Icon(
+                    imageVector = Icons.Filled.Check,
+                    contentDescription = null,
+                    modifier = Modifier.size(SwitchDefaults.IconSize),
+                )
+            }
+            Box(wrapperModifier) {
+                Switch(
+                    checked = true,
+                    onCheckedChange = { },
+                    thumbContent = icon
+                )
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_checked_icon")
+    }
+
+    @Test
+    fun switchTest_unchecked_icon() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            val icon: @Composable () -> Unit = {
+                Icon(
+                    imageVector = Icons.Filled.Close,
+                    contentDescription = null,
+                    modifier = Modifier.size(SwitchDefaults.IconSize),
+                )
+            }
+            Box(wrapperModifier) {
+                Switch(
+                    checked = false,
+                    onCheckedChange = { },
+                    thumbContent = icon
+                )
+            }
+        }
+
+        assertToggeableAgainstGolden("switch_${scheme.name}_unchecked_icon")
+    }
+
+    private fun assertToggeableAgainstGolden(goldenName: String) {
+        rule.onNodeWithTag(wrapperTestTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenName)
+    }
+
+    // Provide the ColorScheme and their name parameter in a ColorSchemeWrapper.
+    // This makes sure that the default method name and the initial Scuba image generated
+    // name is as expected.
+    companion object {
+        @OptIn(ExperimentalTvMaterial3Api::class)
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun parameters() = arrayOf(
+            ColorSchemeWrapper("lightTheme", lightColorScheme()),
+            ColorSchemeWrapper("darkTheme", darkColorScheme()),
+        )
+    }
+
+    @OptIn(ExperimentalTvMaterial3Api::class)
+    class ColorSchemeWrapper constructor(val name: String, val colorScheme: ColorScheme) {
+        override fun toString(): String {
+            return name
+        }
+    }
+}
\ No newline at end of file
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/SwitchTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/SwitchTest.kt
new file mode 100644
index 0000000..fbe4bb2
--- /dev/null
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/SwitchTest.kt
@@ -0,0 +1,319 @@
+/*
+ * 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.tv.material3
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveableStateHolder
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.semantics.focused
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.assertHasNoClickAction
+import androidx.compose.ui.test.assertIsEnabled
+import androidx.compose.ui.test.assertIsOff
+import androidx.compose.ui.test.assertIsOn
+import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
+import androidx.compose.ui.test.isFocusable
+import androidx.compose.ui.test.isNotFocusable
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performKeyInput
+import androidx.compose.ui.test.pressKey
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalTestApi::class, ExperimentalTvMaterial3Api::class)
+class SwitchTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val defaultSwitchTag = "switch"
+
+    @Test
+    fun switch_defaultSemantics() {
+        rule.setMaterialContent(lightColorScheme()) {
+            Column {
+                Switch(
+                    modifier = Modifier.testTag("checked"),
+                    checked = true,
+                    onCheckedChange = {})
+                Switch(
+                    modifier = Modifier.testTag("unchecked"),
+                    checked = false,
+                    onCheckedChange = {}
+                )
+            }
+        }
+
+        rule.onNodeWithTag("checked")
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Switch))
+            .assertIsEnabled()
+            .assertIsOn()
+        rule.onNodeWithTag("unchecked")
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Switch))
+            .assertIsEnabled()
+            .assertIsOff()
+    }
+
+    @Test
+    fun switch_toggle() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val (checked, onChecked) = remember { mutableStateOf(false) }
+
+            // Box is needed because otherwise the control will be expanded to fill its parent
+            Box {
+                Switch(
+                    modifier = Modifier.testTag(defaultSwitchTag),
+                    checked = checked,
+                    onCheckedChange = onChecked
+                )
+            }
+        }
+
+        rule.onNodeWithTag(defaultSwitchTag)
+            .assertIsOff()
+            .performClick()
+            .assertIsOn()
+    }
+
+    @Test
+    fun switch_toggleTwice() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val (checked, onChecked) = remember { mutableStateOf(false) }
+
+            // Box is needed because otherwise the control will be expanded to fill its parent
+            Box {
+                Switch(
+                    modifier = Modifier.testTag(defaultSwitchTag),
+                    checked = checked,
+                    onCheckedChange = onChecked
+                )
+            }
+        }
+
+        rule.onNodeWithTag(defaultSwitchTag)
+            .assertIsOff()
+            .performClick()
+            .assertIsOn()
+            .performClick()
+            .assertIsOff()
+    }
+
+    @Test
+    fun switch_uncheckableWithNoLambda() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val (checked, _) = remember { mutableStateOf(false) }
+            Switch(
+                modifier = Modifier.testTag(defaultSwitchTag),
+                checked = checked,
+                onCheckedChange = {},
+                enabled = false
+            )
+        }
+
+        rule.onNodeWithTag(defaultSwitchTag)
+            .assertHasClickAction()
+    }
+
+    @Test
+    fun switch_untoggleable_whenEmptyLambda() {
+        val parentTag = "parent"
+        rule.setMaterialContent(lightColorScheme()) {
+            val (checked, _) = remember { mutableStateOf(false) }
+            Box(
+                Modifier
+                    .semantics(mergeDescendants = true) {}
+                    .testTag(parentTag)) {
+                Switch(
+                    checked,
+                    {},
+                    enabled = false,
+                    modifier = Modifier
+                        .testTag(defaultSwitchTag)
+                        .semantics { focused = true }
+                )
+            }
+        }
+
+        rule.onNodeWithTag(defaultSwitchTag)
+            .assertHasClickAction()
+
+        // Check not merged into parent
+        rule.onNodeWithTag(parentTag)
+            .assert(isNotFocusable())
+    }
+
+    @Test
+    fun switch_untoggleableAndMergeable_whenNullLambda() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val (checked, _) = remember { mutableStateOf(false) }
+            Box(
+                Modifier
+                    .semantics(mergeDescendants = true) {}
+                    .testTag(defaultSwitchTag)) {
+                Switch(
+                    checked,
+                    null,
+                    modifier = Modifier.semantics { focused = true }
+                )
+            }
+        }
+
+        rule.onNodeWithTag(defaultSwitchTag)
+            .assertHasNoClickAction()
+            .assert(isFocusable()) // Check merged into parent
+    }
+
+    @Test
+    fun switch_stateChange_movesThumb() {
+        var checked by mutableStateOf(false)
+        rule.setMaterialContent(lightColorScheme()) {
+            val spacer = @Composable {
+                Spacer(
+                    Modifier
+                        .size(16.dp)
+                        .testTag("spacer")
+                )
+            }
+            Switch(
+                modifier = Modifier.testTag(defaultSwitchTag),
+                checked = checked,
+                thumbContent = spacer,
+                onCheckedChange = { checked = it },
+            )
+        }
+
+        rule.onNodeWithTag("spacer", useUnmergedTree = true)
+            .assertLeftPositionInRootIsEqualTo(8.dp)
+
+        rule.runOnIdle { checked = true }
+
+        rule.onNodeWithTag("spacer", useUnmergedTree = true)
+            .assertLeftPositionInRootIsEqualTo(28.dp)
+
+        rule.runOnIdle { checked = false }
+
+        rule.onNodeWithTag("spacer", useUnmergedTree = true)
+            .assertLeftPositionInRootIsEqualTo(8.dp)
+    }
+
+    @Test
+    fun switch_constantState_doesNotAnimate() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val spacer = @Composable {
+                Spacer(
+                    Modifier
+                        .size(16.dp)
+                        .testTag("spacer")
+                )
+            }
+            Switch(
+                modifier = Modifier.testTag(defaultSwitchTag),
+                checked = false,
+                thumbContent = spacer,
+                onCheckedChange = {},
+            )
+        }
+
+        rule.onNodeWithTag(defaultSwitchTag)
+            .performKeyInput {
+                pressKey(Key.DirectionCenter)
+            }
+
+        rule.onNodeWithTag("spacer", useUnmergedTree = true)
+            .assertLeftPositionInRootIsEqualTo(8.dp)
+    }
+
+    // regression test for b/191375128
+    @Test
+    fun switch_stateRestoration_stateChangeWhileSaved() {
+        val screenTwo = mutableStateOf(false)
+        var items by mutableStateOf(listOf(1 to false, 2 to true))
+        rule.setMaterialContent(lightColorScheme()) {
+            Column {
+                Button(onClick = { screenTwo.value = !screenTwo.value }) {
+                    Text("switch screen")
+                }
+                val holder = rememberSaveableStateHolder()
+                holder.SaveableStateProvider(screenTwo.value) {
+                    if (screenTwo.value) {
+                        // second screen, just some random content
+                        Text("Second screen")
+                    } else {
+                        Column {
+                            Text("screen one")
+                            items.forEachIndexed { index, item ->
+                                Row {
+                                    Text("Item ${item.first}")
+                                    Switch(
+                                        modifier = Modifier.testTag(item.first.toString()),
+                                        checked = item.second,
+                                        onCheckedChange = {
+                                            items = items.toMutableList().also {
+                                                it[index] = item.first to !item.second
+                                            }
+                                        }
+                                    )
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag("1").assertIsOff()
+        rule.onNodeWithTag("2").assertIsOn()
+        rule.runOnIdle {
+            screenTwo.value = true
+        }
+        rule.runOnIdle {
+            items = items.toMutableList().also {
+                it[0] = items[0].first to !items[0].second
+                it[1] = items[1].first to !items[1].second
+            }
+        }
+        rule.runOnIdle {
+            screenTwo.value = false
+        }
+        rule.onNodeWithTag("1").assertIsOn()
+        rule.onNodeWithTag("2").assertIsOff()
+    }
+}
\ No newline at end of file
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt b/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt
index 50602d5..c8b28a0 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt
@@ -16,9 +16,6 @@
 
 package androidx.tv.material3
 
-import android.view.KeyEvent.KEYCODE_BACK
-import android.view.KeyEvent.KEYCODE_DPAD_LEFT
-import android.view.KeyEvent.KEYCODE_DPAD_RIGHT
 import androidx.compose.animation.AnimatedContent
 import androidx.compose.animation.AnimatedVisibilityScope
 import androidx.compose.animation.ContentTransform
@@ -49,19 +46,25 @@
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusDirection
+import androidx.compose.ui.focus.FocusDirection.Companion.Left
+import androidx.compose.ui.focus.FocusDirection.Companion.Right
 import androidx.compose.ui.focus.FocusManager
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.FocusState
+import androidx.compose.ui.focus.focusProperties
 import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.key.Key
 import androidx.compose.ui.input.key.KeyEventType.Companion.KeyUp
 import androidx.compose.ui.input.key.key
-import androidx.compose.ui.input.key.nativeKeyCode
 import androidx.compose.ui.input.key.onKeyEvent
 import androidx.compose.ui.input.key.type
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.semantics.CollectionInfo
+import androidx.compose.ui.semantics.collectionInfo
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
@@ -127,11 +130,13 @@
         onAutoScrollChange = { isAutoScrollActive = it })
 
     Box(modifier = modifier
+        .semantics {
+            collectionInfo = CollectionInfo(rowCount = 1, columnCount = itemCount)
+        }
         .bringIntoViewIfChildrenAreFocused()
         .focusRequester(carouselOuterBoxFocusRequester)
         .onFocusChanged {
             focusState = it
-
             // When the carousel gains focus for the first time
             if (it.isFocused && isAutoScrollActive) {
                 focusManager.moveFocus(FocusDirection.Enter)
@@ -142,8 +147,8 @@
             outerBoxFocusRequester = carouselOuterBoxFocusRequester,
             focusManager = focusManager,
             itemCount = itemCount,
-            isLtr = isLtr,
-        )
+            isLtr = isLtr
+        ) { focusState }
         .focusable()
     ) {
         AnimatedContent(
@@ -154,7 +159,8 @@
                 } else {
                     contentTransformStartToEnd
                 }
-            }
+            },
+            label = "CarouselAnimation"
         ) { activeItemIndex ->
             LaunchedEffect(Unit) {
                 [email protected] {
@@ -226,69 +232,93 @@
     outerBoxFocusRequester: FocusRequester,
     focusManager: FocusManager,
     itemCount: Int,
-    isLtr: Boolean
+    isLtr: Boolean,
+    currentCarouselBoxFocusState: () -> FocusState?
 ): Modifier = onKeyEvent {
-    // Ignore KeyUp action type
-    if (it.type == KeyUp) {
-        return@onKeyEvent KeyEventPropagation.ContinuePropagation
+    fun showPreviousItem() {
+        carouselState.moveToPreviousItem(itemCount)
+        outerBoxFocusRequester.requestFocus()
+    }
+    fun showNextItem() {
+        carouselState.moveToNextItem(itemCount)
+        outerBoxFocusRequester.requestFocus()
     }
 
-    val showPreviousItemAndGetKeyEventPropagation = {
-        if (carouselState.isFirstItem()) {
-            KeyEventPropagation.ContinuePropagation
-        } else {
-            carouselState.moveToPreviousItem(itemCount)
-            outerBoxFocusRequester.requestFocus()
-            KeyEventPropagation.StopPropagation
-        }
-    }
-    val showNextItemAndGetKeyEventPropagation = {
-        if (carouselState.isLastItem(itemCount)) {
-            KeyEventPropagation.ContinuePropagation
-        } else {
-            carouselState.moveToNextItem(itemCount)
-            outerBoxFocusRequester.requestFocus()
-            KeyEventPropagation.StopPropagation
+    fun updateItemBasedOnLayout(direction: FocusDirection, isLtr: Boolean) {
+        when (direction) {
+            Left -> if (isLtr) showPreviousItem() else showNextItem()
+            Right -> if (isLtr) showNextItem() else showPreviousItem()
         }
     }
 
-    when (it.key.nativeKeyCode) {
-        KEYCODE_BACK -> {
+    fun handledHorizontalFocusMove(direction: FocusDirection): Boolean =
+        when {
+            it.nativeKeyEvent.repeatCount > 0 ->
+                // Ignore long press key event for manual scrolling
+                KeyEventPropagation.StopPropagation
+
+            currentCarouselBoxFocusState()?.isFocused == true ->
+                // if carousel box has focus, do not trigger focus search as it can cause focus to
+                // move out of Carousel unintentionally.
+                if (shouldFocusExitCarousel(direction, carouselState, itemCount, isLtr)) {
+                    KeyEventPropagation.ContinuePropagation
+                } else {
+                    updateItemBasedOnLayout(direction, isLtr)
+                    KeyEventPropagation.StopPropagation
+                }
+
+            !focusManager.moveFocus(direction) -> {
+                // if focus search was unsuccessful, interpret as input for slide change
+                updateItemBasedOnLayout(direction, isLtr)
+                KeyEventPropagation.StopPropagation
+            }
+            else -> KeyEventPropagation.StopPropagation
+        }
+
+    when {
+        // Ignore KeyUp action type
+        it.type == KeyUp -> KeyEventPropagation.ContinuePropagation
+        it.key == Key.Back -> {
             focusManager.moveFocus(FocusDirection.Exit)
             KeyEventPropagation.ContinuePropagation
         }
 
-        KEYCODE_DPAD_LEFT -> {
-            // Ignore long press key event for manual scrolling
-            if (it.nativeKeyEvent.repeatCount > 0) {
-                return@onKeyEvent KeyEventPropagation.StopPropagation
-            }
-
-            if (isLtr) {
-                showPreviousItemAndGetKeyEventPropagation()
-            } else {
-                showNextItemAndGetKeyEventPropagation()
-            }
-        }
-
-        KEYCODE_DPAD_RIGHT -> {
-            // Ignore long press key event for manual scrolling
-            if (it.nativeKeyEvent.repeatCount > 0) {
-                return@onKeyEvent KeyEventPropagation.StopPropagation
-            }
-
-            if (isLtr) {
-                showNextItemAndGetKeyEventPropagation()
-            } else {
-                showPreviousItemAndGetKeyEventPropagation()
-            }
-        }
+        it.key == Key.DirectionLeft -> handledHorizontalFocusMove(Left)
+        it.key == Key.DirectionRight -> handledHorizontalFocusMove(Right)
 
         else -> KeyEventPropagation.ContinuePropagation
     }
+}.focusProperties {
+    // allow exit along horizontal axis only for first and last slide.
+    exit = {
+        when {
+            shouldFocusExitCarousel(it, carouselState, itemCount, isLtr) ->
+                FocusRequester.Default
+            else -> FocusRequester.Cancel
+        }
+    }
 }
 
 @OptIn(ExperimentalTvMaterial3Api::class)
+private fun shouldFocusExitCarousel(
+    focusDirection: FocusDirection,
+    carouselState: CarouselState,
+    itemCount: Int,
+    isLtr: Boolean
+): Boolean =
+    when {
+        // LTR: Don't exit if not first item
+        focusDirection == Left && isLtr && !carouselState.isFirstItem() -> false
+        // RTL: Don't exit if it is not the last item
+        focusDirection == Left && !isLtr && !carouselState.isLastItem(itemCount) -> false
+        // LTR: Don't exit if not last item
+        focusDirection == Right && isLtr && !carouselState.isLastItem(itemCount) -> false
+        // RTL: Don't exit if it is not the first item
+        focusDirection == Right && !isLtr && !carouselState.isFirstItem() -> false
+        else -> true
+    }
+
+@OptIn(ExperimentalTvMaterial3Api::class)
 @Composable
 private fun CarouselStateUpdater(carouselState: CarouselState, itemCount: Int) {
     LaunchedEffect(carouselState, itemCount) {
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/CarouselItem.kt b/tv/tv-material/src/main/java/androidx/tv/material3/CarouselItem.kt
index 2996e8d..bb10fd9 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/CarouselItem.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/CarouselItem.kt
@@ -16,12 +16,15 @@
 
 package androidx.tv.material3
 
+import android.content.Context
+import android.view.accessibility.AccessibilityManager
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.ContentTransform
 import androidx.compose.animation.ExperimentalAnimationApi
 import androidx.compose.animation.slideInHorizontally
 import androidx.compose.animation.slideOutHorizontally
 import androidx.compose.animation.togetherWith
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
@@ -37,8 +40,13 @@
 import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.input.key.onKeyEvent
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.semantics.CollectionItemInfo
+import androidx.compose.ui.semantics.collectionItemInfo
+import androidx.compose.ui.semantics.isContainer
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.tv.material3.KeyEventPropagation.ContinuePropagation
 
@@ -67,6 +75,10 @@
         CarouselItemDefaults.contentTransformStartToEnd,
     content: @Composable () -> Unit,
 ) {
+    val context = LocalContext.current
+    val accessibilityManager = remember {
+        context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
+    }
     var containerBoxFocusState: FocusState? by remember { mutableStateOf(null) }
     val focusManager = LocalFocusManager.current
     var exitFocus by remember { mutableStateOf(false) }
@@ -81,6 +93,16 @@
     // This box holds the focus until the overlay animation completes
     Box(
         modifier = modifier
+            .semantics(mergeDescendants = true) {
+                isContainer = true
+                collectionItemInfo =
+                    CollectionItemInfo(
+                        rowIndex = 0,
+                        rowSpan = 1,
+                        columnIndex = itemIndex,
+                        columnSpan = 1
+                    )
+            }
             .onKeyEvent {
                 exitFocus = it.isBackPress() && it.isTypeKeyDown()
                 ContinuePropagation
@@ -92,7 +114,14 @@
                     exitFocus = false
                 }
             }
-            .focusable()
+            .then(
+                if (accessibilityManager.isEnabled)
+                    Modifier.clickable {
+                        focusManager.moveFocus(FocusDirection.Enter)
+                    }
+                else
+                    Modifier.focusable()
+            )
     ) {
         background()
 
@@ -102,7 +131,10 @@
             exit = contentTransform.initialContentExit,
         ) {
             LaunchedEffect(transition.isRunning, containerBoxFocusState?.isFocused) {
-                if (!transition.isRunning && containerBoxFocusState?.isFocused == true) {
+                if (!transition.isRunning &&
+                    containerBoxFocusState?.isFocused == true &&
+                    !accessibilityManager.isEnabled
+                ) {
                     focusManager.moveFocus(FocusDirection.Enter)
                 }
             }
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/RadioButton.kt b/tv/tv-material/src/main/java/androidx/tv/material3/RadioButton.kt
new file mode 100644
index 0000000..33e5a85
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/RadioButton.kt
@@ -0,0 +1,209 @@
+/*
+ * 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.tv.material3
+
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.animation.core.animateDpAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.selection.selectable
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.drawscope.Fill
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.unit.dp
+import androidx.tv.material3.tokens.RadioButtonTokens
+
+/**
+ * <a href="https://m3.material.io/components/radio-button/overview" class="external" target="_blank">Material Design radio button</a>.
+ *
+ * Radio buttons allow users to select one option from a set.
+ *
+ * ![Radio button image](https://developer.android.com/images/reference/androidx/compose/material3/radio-button.png)
+ *
+ * @param selected whether this radio button is selected or not
+ * @param onClick called when this radio button is clicked. If `null`, then this radio button will
+ * not be interactable, unless something else handles its input events and updates its state.
+ * @param modifier the [Modifier] to be applied to this radio button
+ * @param enabled controls the enabled state of this radio button. When `false`, this component will
+ * not respond to user input, and it will appear visually disabled and disabled to accessibility
+ * services.
+ * @param colors [RadioButtonColors] that will be used to resolve the color used for this radio
+ * button in different states. See [RadioButtonDefaults.colors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this radio button. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this radio button in different states.
+ */
+@ExperimentalTvMaterial3Api
+@Composable
+fun RadioButton(
+    selected: Boolean,
+    onClick: (() -> Unit)?,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    colors: RadioButtonColors = RadioButtonDefaults.colors(),
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
+) {
+    val dotRadius = animateDpAsState(
+        targetValue = if (selected) RadioButtonDotSize / 2 else 0.dp,
+        animationSpec = tween(durationMillis = RadioAnimationDuration)
+    )
+    val radioColor = colors.radioColor(enabled, selected)
+    val selectableModifier =
+        if (onClick != null) {
+            Modifier.selectable(
+                selected = selected,
+                onClick = onClick,
+                enabled = enabled,
+                role = Role.RadioButton,
+                interactionSource = interactionSource,
+                indication = null
+            )
+        } else {
+            Modifier
+        }
+    Canvas(
+        modifier
+            .then(selectableModifier)
+            .wrapContentSize(Alignment.Center)
+            .padding(RadioButtonPadding)
+            .requiredSize(RadioButtonTokens.IconSize)
+    ) {
+        // Draw the radio button
+        val strokeWidth = RadioStrokeWidth.toPx()
+        drawCircle(
+            radioColor.value,
+            radius = (RadioButtonTokens.IconSize / 2).toPx() - strokeWidth / 2,
+            style = Stroke(strokeWidth)
+        )
+        if (dotRadius.value > 0.dp) {
+            drawCircle(radioColor.value, dotRadius.value.toPx() - strokeWidth / 2, style = Fill)
+        }
+    }
+}
+
+/**
+ * Defaults used in [RadioButton].
+ */
+@ExperimentalTvMaterial3Api
+object RadioButtonDefaults {
+    /**
+     * Creates a [RadioButtonColors] that will animate between the provided colors according to
+     * the Material specification.
+     *
+     * @param selectedColor the color to use for the RadioButton when selected and enabled.
+     * @param unselectedColor the color to use for the RadioButton when unselected and enabled.
+     * @param disabledSelectedColor the color to use for the RadioButton when disabled and selected.
+     * @param disabledUnselectedColor the color to use for the RadioButton when disabled and not
+     * selected.
+     * @return the resulting [RadioButtonColors] used for the RadioButton
+     */
+    @Composable
+    fun colors(
+        selectedColor: Color = RadioButtonTokens.SelectedIconColor.toColor(),
+        unselectedColor: Color = RadioButtonTokens.UnselectedIconColor.toColor(),
+        disabledSelectedColor: Color = RadioButtonTokens.DisabledSelectedIconColor
+            .toColor()
+            .copy(alpha = RadioButtonTokens.DisabledSelectedIconOpacity),
+        disabledUnselectedColor: Color = RadioButtonTokens.DisabledUnselectedIconColor
+            .toColor()
+            .copy(alpha = RadioButtonTokens.DisabledUnselectedIconOpacity)
+    ): RadioButtonColors = RadioButtonColors(
+        selectedColor,
+        unselectedColor,
+        disabledSelectedColor,
+        disabledUnselectedColor
+    )
+}
+
+/**
+ * Represents the color used by a [RadioButton] in different states.
+ *
+ * See [RadioButtonDefaults.colors] for the default implementation that follows Material
+ * specifications.
+ */
+@ExperimentalTvMaterial3Api
+@Immutable
+class RadioButtonColors internal constructor(
+    private val selectedColor: Color,
+    private val unselectedColor: Color,
+    private val disabledSelectedColor: Color,
+    private val disabledUnselectedColor: Color
+) {
+    /**
+     * Represents the main color used to draw the outer and inner circles, depending on whether
+     * the [RadioButton] is [enabled] / [selected].
+     *
+     * @param enabled whether the [RadioButton] is enabled
+     * @param selected whether the [RadioButton] is selected
+     */
+    @Composable
+    internal fun radioColor(enabled: Boolean, selected: Boolean): State<Color> {
+        val target = when {
+            enabled && selected -> selectedColor
+            enabled && !selected -> unselectedColor
+            !enabled && selected -> disabledSelectedColor
+            else -> disabledUnselectedColor
+        }
+
+        // If not enabled 'snap' to the disabled state, as there should be no animations between
+        // enabled / disabled.
+        return if (enabled) {
+            animateColorAsState(target, tween(durationMillis = RadioAnimationDuration))
+        } else {
+            rememberUpdatedState(target)
+        }
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is RadioButtonColors) return false
+
+        if (selectedColor != other.selectedColor) return false
+        if (unselectedColor != other.unselectedColor) return false
+        if (disabledSelectedColor != other.disabledSelectedColor) return false
+        if (disabledUnselectedColor != other.disabledUnselectedColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = selectedColor.hashCode()
+        result = 31 * result + unselectedColor.hashCode()
+        result = 31 * result + disabledSelectedColor.hashCode()
+        result = 31 * result + disabledUnselectedColor.hashCode()
+        return result
+    }
+}
+
+private const val RadioAnimationDuration = 100
+
+private val RadioButtonPadding = 2.dp
+private val RadioButtonDotSize = 12.dp
+private val RadioStrokeWidth = 2.dp
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/Switch.kt b/tv/tv-material/src/main/java/androidx/tv/material3/Switch.kt
new file mode 100644
index 0000000..936056a
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/Switch.kt
@@ -0,0 +1,469 @@
+/*
+ * 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.tv.material3
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.TweenSpec
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.indication
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.collectIsPressedAsState
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.selection.toggleable
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.dp
+import androidx.tv.material3.tokens.SwitchTokens
+import kotlin.math.roundToInt
+import kotlinx.coroutines.launch
+
+/**
+ * <a href="https://m3.material.io/components/switch" class="external" target="_blank">Material Design Switch</a>.
+ *
+ * Switches toggle the state of a single item on or off.
+ *
+ * ![Switch image](https://developer.android.com/images/reference/androidx/compose/material3/switch.png)
+ *
+ * Switch can be used with a custom icon via [thumbContent] parameter
+ *
+ * @param checked whether or not this switch is checked
+ * @param onCheckedChange called when this switch is clicked. If `null`, then this switch will not
+ * be interactable, unless something else handles its input events and updates its state.
+ * @param modifier the [Modifier] to be applied to this switch
+ * @param thumbContent content that will be drawn inside the thumb, expected to measure
+ * [SwitchDefaults.IconSize]
+ * @param enabled controls the enabled state of this switch. When `false`, this component will not
+ * respond to user input, and it will appear visually disabled and disabled to accessibility
+ * services.
+ * @param colors [SwitchColors] that will be used to resolve the colors used for this switch in
+ * different states. See [SwitchDefaults.colors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this switch. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this switch in different states.
+ */
+@ExperimentalTvMaterial3Api
+@Composable
+@Suppress("ComposableLambdaParameterNaming", "ComposableLambdaParameterPosition")
+fun Switch(
+    checked: Boolean,
+    onCheckedChange: ((Boolean) -> Unit)?,
+    modifier: Modifier = Modifier,
+    thumbContent: (@Composable () -> Unit)? = null,
+    enabled: Boolean = true,
+    colors: SwitchColors = SwitchDefaults.colors(),
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+) {
+    val uncheckedThumbDiameter = if (thumbContent == null) {
+        UncheckedThumbDiameter
+    } else {
+        ThumbDiameter
+    }
+
+    val thumbPaddingStart = (SwitchHeight - uncheckedThumbDiameter) / 2
+    val minBound = with(LocalDensity.current) { thumbPaddingStart.toPx() }
+    val maxBound = with(LocalDensity.current) { ThumbPathLength.toPx() }
+    val valueToOffset = remember<(Boolean) -> Float>(minBound, maxBound) {
+        { value -> if (value) maxBound else minBound }
+    }
+
+    val targetValue = valueToOffset(checked)
+    val offset = remember { Animatable(targetValue) }
+    val scope = rememberCoroutineScope()
+
+    SideEffect {
+        // min bound might have changed if the icon is only rendered in checked state.
+        offset.updateBounds(lowerBound = minBound)
+    }
+
+    DisposableEffect(checked) {
+        if (offset.targetValue != targetValue) {
+            scope.launch {
+                offset.animateTo(targetValue, AnimationSpec)
+            }
+        }
+        onDispose { }
+    }
+
+    // TODO: Add Swipeable modifier b/223797571
+    val toggleableModifier =
+        if (onCheckedChange != null) {
+            Modifier.toggleable(
+                value = checked,
+                onValueChange = onCheckedChange,
+                enabled = enabled,
+                role = Role.Switch,
+                interactionSource = interactionSource,
+                indication = null
+            )
+        } else {
+            Modifier
+        }
+
+    Box(
+        modifier
+            .then(toggleableModifier)
+            .wrapContentSize(Alignment.Center)
+            .requiredSize(SwitchWidth, SwitchHeight)
+    ) {
+        SwitchImpl(
+            checked = checked,
+            enabled = enabled,
+            colors = colors,
+            thumbValue = offset.asState(),
+            interactionSource = interactionSource,
+            thumbShape = SwitchTokens.HandleShape.toShape(),
+            uncheckedThumbDiameter = uncheckedThumbDiameter,
+            minBound = thumbPaddingStart,
+            maxBound = ThumbPathLength,
+            thumbContent = thumbContent,
+        )
+    }
+}
+
+@OptIn(ExperimentalTvMaterial3Api::class)
+@Composable
+@Suppress("ComposableLambdaParameterNaming", "ComposableLambdaParameterPosition")
+private fun BoxScope.SwitchImpl(
+    checked: Boolean,
+    enabled: Boolean,
+    colors: SwitchColors,
+    thumbValue: State<Float>,
+    thumbContent: (@Composable () -> Unit)?,
+    interactionSource: InteractionSource,
+    thumbShape: Shape,
+    uncheckedThumbDiameter: Dp,
+    minBound: Dp,
+    maxBound: Dp,
+) {
+    val trackColor by colors.trackColor(enabled, checked)
+    val isPressed by interactionSource.collectIsPressedAsState()
+
+    val thumbValueDp = with(LocalDensity.current) { thumbValue.value.toDp() }
+    val thumbSizeDp = if (isPressed) {
+        SwitchTokens.PressedHandleWidth
+    } else {
+        uncheckedThumbDiameter + (ThumbDiameter - uncheckedThumbDiameter) *
+            ((thumbValueDp - minBound) / (maxBound - minBound))
+    }
+
+    val thumbOffset = if (isPressed) {
+        with(LocalDensity.current) {
+            if (checked) {
+                ThumbPathLength - SwitchTokens.TrackOutlineWidth
+            } else {
+                SwitchTokens.TrackOutlineWidth
+            }.toPx()
+        }
+    } else {
+        thumbValue.value
+    }
+
+    val trackShape = SwitchTokens.TrackShape.toShape()
+    val modifier = Modifier
+        .align(Alignment.Center)
+        .width(SwitchWidth)
+        .height(SwitchHeight)
+        .border(
+            SwitchTokens.TrackOutlineWidth,
+            colors.borderColor(enabled, checked).value,
+            trackShape
+        )
+        .background(trackColor, trackShape)
+
+    Box(modifier) {
+        val thumbColor by colors.thumbColor(enabled, checked)
+        val resolvedThumbColor = thumbColor
+        Box(
+            modifier = Modifier
+                .align(Alignment.CenterStart)
+                .offset { IntOffset(thumbOffset.roundToInt(), 0) }
+                .indication(
+                    interactionSource = interactionSource,
+                    indication = null
+                )
+                .requiredSize(thumbSizeDp)
+                .background(resolvedThumbColor, thumbShape),
+            contentAlignment = Alignment.Center
+        ) {
+            if (thumbContent != null) {
+                val iconColor = colors.iconColor(enabled, checked)
+                CompositionLocalProvider(
+                    LocalContentColor provides iconColor.value,
+                    content = thumbContent
+                )
+            }
+        }
+    }
+}
+
+internal val ThumbDiameter = SwitchTokens.SelectedHandleWidth
+internal val UncheckedThumbDiameter = SwitchTokens.UnselectedHandleWidth
+private val SwitchWidth = SwitchTokens.TrackWidth
+private val SwitchHeight = SwitchTokens.TrackHeight
+private val ThumbPadding = (SwitchHeight - ThumbDiameter) / 2
+private val ThumbPathLength = (SwitchWidth - ThumbDiameter) - ThumbPadding
+
+private val AnimationSpec = TweenSpec<Float>(durationMillis = 100)
+
+/**
+ * Contains the default values used by [Switch]
+ */
+@ExperimentalTvMaterial3Api
+object SwitchDefaults {
+    /**
+     * Creates a [SwitchColors] that represents the different colors used in a [Switch] in
+     * different states.
+     *
+     * @param checkedThumbColor the color used for the thumb when enabled and checked
+     * @param checkedTrackColor the color used for the track when enabled and checked
+     * @param checkedBorderColor the color used for the border when enabled and checked
+     * @param checkedIconColor the color used for the icon when enabled and checked
+     * @param uncheckedThumbColor the color used for the thumb when enabled and unchecked
+     * @param uncheckedTrackColor the color used for the track when enabled and unchecked
+     * @param uncheckedBorderColor the color used for the border when enabled and unchecked
+     * @param uncheckedIconColor the color used for the icon when enabled and unchecked
+     * @param disabledCheckedThumbColor the color used for the thumb when disabled and checked
+     * @param disabledCheckedTrackColor the color used for the track when disabled and checked
+     * @param disabledCheckedBorderColor the color used for the border when disabled and checked
+     * @param disabledCheckedIconColor the color used for the icon when disabled and checked
+     * @param disabledUncheckedThumbColor the color used for the thumb when disabled and unchecked
+     * @param disabledUncheckedTrackColor the color used for the track when disabled and unchecked
+     * @param disabledUncheckedBorderColor the color used for the border when disabled and unchecked
+     * @param disabledUncheckedIconColor the color used for the icon when disabled and unchecked
+     */
+    @Composable
+    fun colors(
+        checkedThumbColor: Color = SwitchTokens.SelectedHandleColor.toColor(),
+        checkedTrackColor: Color = SwitchTokens.SelectedTrackColor.toColor(),
+        checkedBorderColor: Color = Color.Transparent,
+        checkedIconColor: Color = SwitchTokens.SelectedIconColor.toColor(),
+        uncheckedThumbColor: Color = SwitchTokens.UnselectedHandleColor.toColor(),
+        uncheckedTrackColor: Color = SwitchTokens.UnselectedTrackColor.toColor(),
+        uncheckedBorderColor: Color = SwitchTokens.UnselectedFocusTrackOutlineColor.toColor(),
+        uncheckedIconColor: Color = SwitchTokens.UnselectedIconColor.toColor(),
+        disabledCheckedThumbColor: Color = SwitchTokens.DisabledSelectedHandleColor.toColor()
+            .copy(alpha = SwitchTokens.DisabledSelectedHandleOpacity)
+            .compositeOver(MaterialTheme.colorScheme.surface),
+        disabledCheckedTrackColor: Color = SwitchTokens.DisabledSelectedTrackColor.toColor()
+            .copy(alpha = SwitchTokens.DisabledTrackOpacity)
+            .compositeOver(MaterialTheme.colorScheme.surface),
+        disabledCheckedBorderColor: Color = Color.Transparent,
+        disabledCheckedIconColor: Color = SwitchTokens.DisabledSelectedIconColor.toColor()
+            .copy(alpha = SwitchTokens.DisabledSelectedIconOpacity)
+            .compositeOver(MaterialTheme.colorScheme.surface),
+        disabledUncheckedThumbColor: Color = SwitchTokens.DisabledUnselectedHandleColor.toColor()
+            .copy(alpha = SwitchTokens.DisabledUnselectedHandleOpacity)
+            .compositeOver(MaterialTheme.colorScheme.surface),
+        disabledUncheckedTrackColor: Color = SwitchTokens.DisabledUnselectedTrackColor.toColor()
+            .copy(alpha = SwitchTokens.DisabledTrackOpacity)
+            .compositeOver(MaterialTheme.colorScheme.surface),
+        disabledUncheckedBorderColor: Color =
+            SwitchTokens.DisabledUnselectedTrackOutlineColor.toColor()
+                .copy(alpha = SwitchTokens.DisabledTrackOpacity)
+                .compositeOver(MaterialTheme.colorScheme.surface),
+        disabledUncheckedIconColor: Color = SwitchTokens.DisabledUnselectedIconColor.toColor()
+            .copy(alpha = SwitchTokens.DisabledUnselectedIconOpacity)
+            .compositeOver(MaterialTheme.colorScheme.surface),
+    ): SwitchColors = SwitchColors(
+        checkedThumbColor = checkedThumbColor,
+        checkedTrackColor = checkedTrackColor,
+        checkedBorderColor = checkedBorderColor,
+        checkedIconColor = checkedIconColor,
+        uncheckedThumbColor = uncheckedThumbColor,
+        uncheckedTrackColor = uncheckedTrackColor,
+        uncheckedBorderColor = uncheckedBorderColor,
+        uncheckedIconColor = uncheckedIconColor,
+        disabledCheckedThumbColor = disabledCheckedThumbColor,
+        disabledCheckedTrackColor = disabledCheckedTrackColor,
+        disabledCheckedBorderColor = disabledCheckedBorderColor,
+        disabledCheckedIconColor = disabledCheckedIconColor,
+        disabledUncheckedThumbColor = disabledUncheckedThumbColor,
+        disabledUncheckedTrackColor = disabledUncheckedTrackColor,
+        disabledUncheckedBorderColor = disabledUncheckedBorderColor,
+        disabledUncheckedIconColor = disabledUncheckedIconColor
+    )
+
+    /**
+     * Icon size to use for `thumbContent`
+     */
+    val IconSize = 16.dp
+}
+
+/**
+ * Represents the colors used by a [Switch] in different states
+ *
+ * See [SwitchDefaults.colors] for the default implementation that follows Material
+ * specifications.
+ */
+@ExperimentalTvMaterial3Api
+@Immutable
+class SwitchColors internal constructor(
+    private val checkedThumbColor: Color,
+    private val checkedTrackColor: Color,
+    private val checkedBorderColor: Color,
+    private val checkedIconColor: Color,
+    private val uncheckedThumbColor: Color,
+    private val uncheckedTrackColor: Color,
+    private val uncheckedBorderColor: Color,
+    private val uncheckedIconColor: Color,
+    private val disabledCheckedThumbColor: Color,
+    private val disabledCheckedTrackColor: Color,
+    private val disabledCheckedBorderColor: Color,
+    private val disabledCheckedIconColor: Color,
+    private val disabledUncheckedThumbColor: Color,
+    private val disabledUncheckedTrackColor: Color,
+    private val disabledUncheckedBorderColor: Color,
+    private val disabledUncheckedIconColor: Color
+) {
+    /**
+     * Represents the color used for the switch's thumb, depending on [enabled] and [checked].
+     *
+     * @param enabled whether the [Switch] is enabled or not
+     * @param checked whether the [Switch] is checked or not
+     */
+    @Composable
+    internal fun thumbColor(enabled: Boolean, checked: Boolean): State<Color> {
+        return rememberUpdatedState(
+            if (enabled) {
+                if (checked) checkedThumbColor else uncheckedThumbColor
+            } else {
+                if (checked) disabledCheckedThumbColor else disabledUncheckedThumbColor
+            }
+        )
+    }
+
+    /**
+     * Represents the color used for the switch's track, depending on [enabled] and [checked].
+     *
+     * @param enabled whether the [Switch] is enabled or not
+     * @param checked whether the [Switch] is checked or not
+     */
+    @Composable
+    internal fun trackColor(enabled: Boolean, checked: Boolean): State<Color> {
+        return rememberUpdatedState(
+            if (enabled) {
+                if (checked) checkedTrackColor else uncheckedTrackColor
+            } else {
+                if (checked) disabledCheckedTrackColor else disabledUncheckedTrackColor
+            }
+        )
+    }
+
+    /**
+     * Represents the color used for the switch's border, depending on [enabled] and [checked].
+     *
+     * @param enabled whether the [Switch] is enabled or not
+     * @param checked whether the [Switch] is checked or not
+     */
+    @Composable
+    internal fun borderColor(enabled: Boolean, checked: Boolean): State<Color> {
+        return rememberUpdatedState(
+            if (enabled) {
+                if (checked) checkedBorderColor else uncheckedBorderColor
+            } else {
+                if (checked) disabledCheckedBorderColor else disabledUncheckedBorderColor
+            }
+        )
+    }
+
+    /**
+     * Represents the content color passed to the icon if used
+     *
+     * @param enabled whether the [Switch] is enabled or not
+     * @param checked whether the [Switch] is checked or not
+     */
+    @Composable
+    internal fun iconColor(enabled: Boolean, checked: Boolean): State<Color> {
+        return rememberUpdatedState(
+            if (enabled) {
+                if (checked) checkedIconColor else uncheckedIconColor
+            } else {
+                if (checked) disabledCheckedIconColor else disabledUncheckedIconColor
+            }
+        )
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is SwitchColors) return false
+
+        if (checkedThumbColor != other.checkedThumbColor) return false
+        if (checkedTrackColor != other.checkedTrackColor) return false
+        if (checkedBorderColor != other.checkedBorderColor) return false
+        if (checkedIconColor != other.checkedIconColor) return false
+        if (uncheckedThumbColor != other.uncheckedThumbColor) return false
+        if (uncheckedTrackColor != other.uncheckedTrackColor) return false
+        if (uncheckedBorderColor != other.uncheckedBorderColor) return false
+        if (uncheckedIconColor != other.uncheckedIconColor) return false
+        if (disabledCheckedThumbColor != other.disabledCheckedThumbColor) return false
+        if (disabledCheckedTrackColor != other.disabledCheckedTrackColor) return false
+        if (disabledCheckedBorderColor != other.disabledCheckedBorderColor) return false
+        if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
+        if (disabledUncheckedThumbColor != other.disabledUncheckedThumbColor) return false
+        if (disabledUncheckedTrackColor != other.disabledUncheckedTrackColor) return false
+        if (disabledUncheckedBorderColor != other.disabledUncheckedBorderColor) return false
+        if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = checkedThumbColor.hashCode()
+        result = 31 * result + checkedTrackColor.hashCode()
+        result = 31 * result + checkedBorderColor.hashCode()
+        result = 31 * result + checkedIconColor.hashCode()
+        result = 31 * result + uncheckedThumbColor.hashCode()
+        result = 31 * result + uncheckedTrackColor.hashCode()
+        result = 31 * result + uncheckedBorderColor.hashCode()
+        result = 31 * result + uncheckedIconColor.hashCode()
+        result = 31 * result + disabledCheckedThumbColor.hashCode()
+        result = 31 * result + disabledCheckedTrackColor.hashCode()
+        result = 31 * result + disabledCheckedBorderColor.hashCode()
+        result = 31 * result + disabledCheckedIconColor.hashCode()
+        result = 31 * result + disabledUncheckedThumbColor.hashCode()
+        result = 31 * result + disabledUncheckedTrackColor.hashCode()
+        result = 31 * result + disabledUncheckedBorderColor.hashCode()
+        result = 31 * result + disabledUncheckedIconColor.hashCode()
+        return result
+    }
+}
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/tokens/RadioButtonTokens.kt b/tv/tv-material/src/main/java/androidx/tv/material3/tokens/RadioButtonTokens.kt
new file mode 100644
index 0000000..fab1c59
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/tokens/RadioButtonTokens.kt
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+// VERSION: v0_001 (Inspired by androidx.compose.material3.tokens v0_103)
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.tv.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object RadioButtonTokens {
+    val DisabledSelectedIconColor = ColorSchemeKeyTokens.OnSurface
+    const val DisabledSelectedIconOpacity = 0.38f
+    val DisabledUnselectedIconColor = ColorSchemeKeyTokens.OnSurface
+    const val DisabledUnselectedIconOpacity = 0.38f
+    val IconSize = 20.0.dp
+    val SelectedFocusIconColor = ColorSchemeKeyTokens.Primary
+    val SelectedHoverIconColor = ColorSchemeKeyTokens.Primary
+    val SelectedIconColor = ColorSchemeKeyTokens.Primary
+    val SelectedPressedIconColor = ColorSchemeKeyTokens.Primary
+    val StateLayerSize = 40.0.dp
+    val UnselectedFocusIconColor = ColorSchemeKeyTokens.OnSurface
+    val UnselectedHoverIconColor = ColorSchemeKeyTokens.OnSurface
+    val UnselectedIconColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val UnselectedPressedIconColor = ColorSchemeKeyTokens.OnSurface
+}
\ No newline at end of file
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/tokens/SwitchTokens.kt b/tv/tv-material/src/main/java/androidx/tv/material3/tokens/SwitchTokens.kt
new file mode 100644
index 0000000..498364f
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/tokens/SwitchTokens.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+// VERSION: v0_001 (Inspired by androidx.compose.material3.tokens v0_103)
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.tv.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object SwitchTokens {
+    val DisabledSelectedHandleColor = ColorSchemeKeyTokens.Surface
+    const val DisabledSelectedHandleOpacity = 1.0f
+    val DisabledSelectedIconColor = ColorSchemeKeyTokens.OnSurface
+    const val DisabledSelectedIconOpacity = 0.38f
+    val DisabledSelectedTrackColor = ColorSchemeKeyTokens.OnSurface
+    const val DisabledTrackOpacity = 0.12f
+    val DisabledUnselectedHandleColor = ColorSchemeKeyTokens.OnSurface
+    const val DisabledUnselectedHandleOpacity = 0.38f
+    val DisabledUnselectedIconColor = ColorSchemeKeyTokens.SurfaceVariant
+    const val DisabledUnselectedIconOpacity = 0.38f
+    val DisabledUnselectedTrackColor = ColorSchemeKeyTokens.SurfaceVariant
+    val DisabledUnselectedTrackOutlineColor = ColorSchemeKeyTokens.OnSurface
+    val HandleShape = ShapeKeyTokens.CornerFull
+    val PressedHandleHeight = 28.0.dp
+    val PressedHandleWidth = 28.0.dp
+    val SelectedFocusHandleColor = ColorSchemeKeyTokens.PrimaryContainer
+    val SelectedFocusIconColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val SelectedFocusTrackColor = ColorSchemeKeyTokens.Primary
+    val SelectedHandleColor = ColorSchemeKeyTokens.OnPrimary
+    val SelectedHandleHeight = 24.0.dp
+    val SelectedHandleWidth = 24.0.dp
+    val SelectedHoverHandleColor = ColorSchemeKeyTokens.PrimaryContainer
+    val SelectedHoverIconColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val SelectedHoverTrackColor = ColorSchemeKeyTokens.Primary
+    val SelectedIconColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val SelectedIconSize = 16.0.dp
+    val SelectedPressedHandleColor = ColorSchemeKeyTokens.PrimaryContainer
+    val SelectedPressedIconColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val SelectedPressedTrackColor = ColorSchemeKeyTokens.Primary
+    val SelectedTrackColor = ColorSchemeKeyTokens.Primary
+    val StateLayerShape = ShapeKeyTokens.CornerFull
+    val StateLayerSize = 40.0.dp
+    val TrackHeight = 32.0.dp
+    val TrackOutlineWidth = 2.0.dp
+    val TrackShape = ShapeKeyTokens.CornerFull
+    val TrackWidth = 52.0.dp
+    val UnselectedFocusHandleColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val UnselectedFocusIconColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedFocusTrackColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedFocusTrackOutlineColor = ColorSchemeKeyTokens.Border
+    val UnselectedHandleColor = ColorSchemeKeyTokens.Border
+    val UnselectedHandleHeight = 16.0.dp
+    val UnselectedHandleWidth = 16.0.dp
+    val UnselectedHoverHandleColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val UnselectedHoverIconColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedHoverTrackColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedHoverTrackOutlineColor = ColorSchemeKeyTokens.Border
+    val UnselectedIconColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedIconSize = 16.0.dp
+    val UnselectedPressedHandleColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val UnselectedPressedIconColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedPressedTrackColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedPressedTrackOutlineColor = ColorSchemeKeyTokens.Border
+    val UnselectedTrackColor = ColorSchemeKeyTokens.SurfaceVariant
+    val UnselectedTrackOutlineColor = ColorSchemeKeyTokens.Border
+    val IconHandleHeight = 24.0.dp
+    val IconHandleWidth = 24.0.dp
+}
\ No newline at end of file
diff --git a/versionedparcelable/versionedparcelable/api/aidlRelease/current/androidx/versionedparcelable/ParcelImpl.aidl b/versionedparcelable/versionedparcelable/api/aidlRelease/current/androidx/versionedparcelable/ParcelImpl.aidl
index 5b1fea6..8d22e67 100644
--- a/versionedparcelable/versionedparcelable/api/aidlRelease/current/androidx/versionedparcelable/ParcelImpl.aidl
+++ b/versionedparcelable/versionedparcelable/api/aidlRelease/current/androidx/versionedparcelable/ParcelImpl.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/wear/compose/compose-foundation/api/public_plus_experimental_current.txt b/wear/compose/compose-foundation/api/public_plus_experimental_current.txt
index cf3e0b0..81af87e 100644
--- a/wear/compose/compose-foundation/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-foundation/api/public_plus_experimental_current.txt
@@ -205,6 +205,11 @@
     method @androidx.compose.runtime.Composable @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public static androidx.compose.ui.focus.FocusRequester rememberActiveFocusRequester();
   }
 
+  @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public interface RevealScope {
+    method public float getRevealOffset();
+    property public abstract float revealOffset;
+  }
+
   @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public final class RevealState {
     method public suspend Object? animateTo(int targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method public int getCurrentValue();
@@ -236,7 +241,7 @@
   }
 
   public final class SwipeToRevealKt {
-    method @androidx.compose.runtime.Composable @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public static void SwipeToReveal(kotlin.jvm.functions.Function0<kotlin.Unit> action, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> onFullSwipe, optional androidx.wear.compose.foundation.RevealState state, optional kotlin.jvm.functions.Function0<kotlin.Unit>? additionalAction, optional kotlin.jvm.functions.Function0<kotlin.Unit>? undoAction, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public static void SwipeToReveal(kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.RevealScope,kotlin.Unit> action, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> onFullSwipe, optional androidx.wear.compose.foundation.RevealState state, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.RevealScope,kotlin.Unit>? additionalAction, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.RevealScope,kotlin.Unit>? undoAction, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public static java.util.Map<androidx.wear.compose.foundation.RevealValue,java.lang.Float> createAnchors(optional float coveredAnchor, optional float revealingAnchor, optional float revealedAnchor);
     method @androidx.compose.runtime.Composable @androidx.wear.compose.foundation.ExperimentalWearFoundationApi public static androidx.wear.compose.foundation.RevealState rememberRevealState(optional int initialValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.RevealValue,java.lang.Boolean> confirmValueChange, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.unit.Density,? super java.lang.Float,java.lang.Float> positionalThreshold, optional java.util.Map<androidx.wear.compose.foundation.RevealValue,java.lang.Float> anchors);
   }
diff --git a/wear/compose/compose-foundation/samples/build.gradle b/wear/compose/compose-foundation/samples/build.gradle
index be551b8..ea89774 100644
--- a/wear/compose/compose-foundation/samples/build.gradle
+++ b/wear/compose/compose-foundation/samples/build.gradle
@@ -30,6 +30,7 @@
     compileOnly(project(":annotation:annotation-sampled"))
     implementation(project(":compose:foundation:foundation"))
     implementation(project(":compose:foundation:foundation-layout"))
+    implementation(project(":compose:material:material-icons-core"))
     implementation(project(":compose:runtime:runtime"))
     implementation(project(":compose:ui:ui"))
     implementation(project(":compose:ui:ui-text"))
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt
new file mode 100644
index 0000000..1212135
--- /dev/null
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt
@@ -0,0 +1,224 @@
+/*
+ * 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.wear.compose.foundation.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CornerSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.Delete
+import androidx.compose.material.icons.outlined.MoreVert
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
+import androidx.wear.compose.foundation.RevealValue
+import androidx.wear.compose.foundation.SwipeToReveal
+import androidx.wear.compose.foundation.expandableItem
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.rememberExpandableState
+import androidx.wear.compose.foundation.rememberRevealState
+import androidx.wear.compose.material.Chip
+import androidx.wear.compose.material.ChipDefaults
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.ListHeader
+import androidx.wear.compose.material.Text
+import kotlin.math.abs
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalWearFoundationApi::class)
+@Sampled
+@Composable
+fun SwipeToRevealSample() {
+    SwipeToReveal(
+        action = {
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .clickable { /* Add the primary action */ },
+            ) {
+                Icon(
+                    imageVector = Icons.Outlined.Delete,
+                    contentDescription = "Delete"
+                )
+            }
+        },
+        undoAction = {
+            Chip(
+                modifier = Modifier.fillMaxWidth(),
+                onClick = { /* Add undo action here */ },
+                colors = ChipDefaults.secondaryChipColors(),
+                label = { Text(text = "Undo") }
+            )
+        }
+    ) {
+        Chip(
+            modifier = Modifier.fillMaxWidth(),
+            onClick = { /* the click action associated with chip */ },
+            colors = ChipDefaults.secondaryChipColors(),
+            label = { Text(text = "Swipe Me") }
+        )
+    }
+}
+
+@OptIn(ExperimentalWearFoundationApi::class)
+@Sampled
+@Composable
+fun SwipeToRevealWithRevealOffset() {
+    val state = rememberRevealState()
+    SwipeToReveal(
+        state = state,
+        action = {
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .clickable { /* Add the primary action */ },
+            ) {
+                Icon(
+                    imageVector = Icons.Outlined.Delete,
+                    contentDescription = "Delete"
+                )
+                if (abs(state.offset) > revealOffset) {
+                    Spacer(Modifier.size(5.dp))
+                    Text("Clear")
+                }
+            }
+        },
+        undoAction = {
+            Chip(
+                modifier = Modifier.fillMaxWidth(),
+                onClick = { /* Add undo action here */ },
+                colors = ChipDefaults.secondaryChipColors(),
+                label = { Text(text = "Undo") }
+            )
+        }
+    ) {
+        Chip(
+            modifier = Modifier.fillMaxWidth(),
+            onClick = { /* the click action associated with chip */ },
+            colors = ChipDefaults.secondaryChipColors(),
+            label = { Text(text = "Swipe Me") }
+        )
+    }
+}
+
+/**
+ * A sample on how to use Swipe To Reveal within a list of items, preferably [ScalingLazyColumn].
+ */
+@OptIn(ExperimentalWearFoundationApi::class)
+@Sampled
+@Composable
+fun SwipeToRevealWithExpandables() {
+    // Shape of actions should match with the overlay content. For example, Chips
+    // should use RoundedCornerShape(CornerSize(percent = 50)), Cards should use
+    // RoundedCornerShape with appropriate radius, based on the theme.
+    val actionShape = RoundedCornerShape(corner = CornerSize(percent = 50))
+    val itemCount = 10
+    val coroutineScope = rememberCoroutineScope()
+    val expandableStates = List(itemCount) {
+        rememberExpandableState(initiallyExpanded = true)
+    }
+    ScalingLazyColumn(
+        modifier = Modifier.fillMaxSize()
+    ) {
+        item {
+            ListHeader {
+                Text("Scaling Lazy Column")
+            }
+        }
+        repeat(itemCount) { current ->
+            expandableItem(
+                state = expandableStates[current],
+            ) { isExpanded ->
+                val revealState = rememberRevealState()
+                if (isExpanded) {
+                    SwipeToReveal(
+                        state = revealState,
+                        action = {
+                            Box(
+                                modifier = Modifier
+                                    .fillMaxSize()
+                                    .background(Color.Red, actionShape)
+                                    .clickable {
+                                        coroutineScope.launch {
+                                            revealState.animateTo(RevealValue.Revealed)
+                                        }
+                                    },
+                                contentAlignment = Alignment.Center
+                            ) {
+                                Icon(
+                                    imageVector = Icons.Outlined.Delete,
+                                    contentDescription = "Delete"
+                                )
+                            }
+                        },
+                        additionalAction = {
+                            Box(
+                                modifier = Modifier
+                                    .fillMaxSize()
+                                    .background(Color.Gray, actionShape)
+                                    .clickable { /* trigger the optional action */ },
+                                contentAlignment = Alignment.Center
+                            ) {
+                                Icon(
+                                    imageVector = Icons.Outlined.MoreVert,
+                                    contentDescription = "More Options"
+                                )
+                            }
+                        },
+                        undoAction = {
+                            Chip(
+                                modifier = Modifier.fillMaxWidth(),
+                                onClick = {
+                                    coroutineScope.launch {
+                                        revealState.animateTo(RevealValue.Covered)
+                                    }
+                                },
+                                colors = ChipDefaults.secondaryChipColors(),
+                                label = { Text(text = "Undo") }
+                            )
+                        },
+                        onFullSwipe = {
+                            coroutineScope.launch {
+                                delay(1000)
+                                expandableStates[current].expanded = false
+                            }
+                        }
+                    ) {
+                        Chip(
+                            modifier = Modifier.fillMaxWidth(),
+                            onClick = { /* the click action associated with chip */ },
+                            colors = ChipDefaults.secondaryChipColors(),
+                            label = { Text(text = "Swipe Me") }
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt b/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt
index 7e65f0e..9f901e2 100644
--- a/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt
+++ b/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt
@@ -138,11 +138,11 @@
 
     @Composable
     private fun swipeToRevealWithDefaults(
-        action: @Composable () -> Unit = { getAction() },
+        action: @Composable RevealScope.() -> Unit = { getAction() },
         state: RevealState = rememberRevealState(),
         modifier: Modifier = Modifier,
-        additionalAction: (@Composable () -> Unit)? = null,
-        undoAction: (@Composable () -> Unit)? = null,
+        additionalAction: (@Composable RevealScope.() -> Unit)? = null,
+        undoAction: (@Composable RevealScope.() -> Unit)? = null,
         content: @Composable () -> Unit = { getBoxContent() }
     ) {
         SwipeToReveal(
diff --git a/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/SwipeToReveal.kt b/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/SwipeToReveal.kt
index 86e8cb6..50764ab 100644
--- a/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/SwipeToReveal.kt
+++ b/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/SwipeToReveal.kt
@@ -32,6 +32,7 @@
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -235,7 +236,14 @@
  * It is strongly recommended to have icons represent the actions and maybe a text and icon for
  * the undo action.
  *
- * TODO: Add Sample
+ * Example of SwipeToReveal with mandatory action and undo action
+ * @sample androidx.wear.compose.foundation.samples.SwipeToRevealSample
+ *
+ * Example of SwipeToReveal using [RevealScope]
+ * @sample androidx.wear.compose.foundation.samples.SwipeToRevealWithRevealOffset
+ *
+ * Example of SwipeToReveal used with Expandables
+ * @sample androidx.wear.compose.foundation.samples.SwipeToRevealWithExpandables
  *
  * @param action The mandatory action that needs to be added to the component.
  * @param modifier Optional [Modifier] for this component.
@@ -251,83 +259,113 @@
 @ExperimentalWearFoundationApi
 @Composable
 public fun SwipeToReveal(
-    action: @Composable () -> Unit,
+    action: @Composable RevealScope.() -> Unit,
     modifier: Modifier = Modifier,
     onFullSwipe: () -> Unit = {},
     state: RevealState = rememberRevealState(),
-    additionalAction: (@Composable () -> Unit)? = null,
-    undoAction: (@Composable () -> Unit)? = null,
+    additionalAction: (@Composable RevealScope.() -> Unit)? = null,
+    undoAction: (@Composable RevealScope.() -> Unit)? = null,
     content: @Composable () -> Unit
-) = Box(
-    modifier = modifier
-        .swipeableV2(
-            state = state.swipeableState,
-            orientation = Orientation.Horizontal,
-            enabled = true,
-        )
-        .swipeAnchors(
-            state = state.swipeableState,
-            possibleValues = state.swipeAnchors.keys
-        ) { value, layoutSize ->
-            val swipeableWidth = layoutSize.width.toFloat()
-            // Multiply the anchor with -1f to get the actual swipeable anchor
-            -state.swipeAnchors[value]!! * swipeableWidth
-        }
 ) {
-    val swipeCompleted by remember {
-        derivedStateOf { state.currentValue == RevealValue.Revealed }
-    }
-    val density = LocalDensity.current
-
-    // Total width available for the slot(s) based on the current swipe offset
-    val availableWidth = if (state.offset.isNaN()) 0.dp
-        else with(density) { abs(state.offset).toDp() }
-    // Total padding between the slots based on the available actions
-    val totalPadding = if (additionalAction != null) SwipeToRevealDefaults.padding * 2
-        else SwipeToRevealDefaults.padding
-
-    Row(
-        modifier = Modifier.matchParentSize(),
-        horizontalArrangement = Arrangement.Absolute.Right
-    ) {
-        if (swipeCompleted && undoAction != null) {
-            Row(
-                modifier = Modifier.fillMaxWidth(),
-                horizontalArrangement = Arrangement.Center
-            ) {
-                ActionSlot(content = undoAction)
-            }
-        } else {
-            Row(
-                modifier = Modifier.width(availableWidth.minus(totalPadding)),
-                horizontalArrangement = Arrangement.Absolute.Right
-            ) {
-                if (additionalAction != null) {
-                    Spacer(Modifier.size(SwipeToRevealDefaults.padding))
-                    ActionSlot(content = additionalAction)
-                }
-                Spacer(Modifier.size(SwipeToRevealDefaults.padding))
-                ActionSlot(content = action)
-            }
-        }
-    }
-    Row(
-        modifier = Modifier.absoluteOffset {
-            IntOffset(
-                x = state.requireOffset().roundToInt().coerceAtMost(0),
-                y = 0
+    // Initialise to zero, updated when the size changes
+    val revealScope = remember(state) { RevealScopeImpl(state) }
+    Box(
+        modifier = modifier
+            .swipeableV2(
+                state = state.swipeableState,
+                orientation = Orientation.Horizontal,
+                enabled = true,
             )
-        }
+            .swipeAnchors(
+                state = state.swipeableState,
+                possibleValues = state.swipeAnchors.keys
+            ) { value, layoutSize ->
+                val swipeableWidth = layoutSize.width.toFloat()
+                // Update the total width which will be used to calculate the anchors
+                revealScope.width.value = swipeableWidth
+                // Multiply the anchor with -1f to get the actual swipeable anchor
+                -state.swipeAnchors[value]!! * swipeableWidth
+            }
     ) {
-        content()
-    }
-    LaunchedEffect(state.currentValue) {
-        if (state.currentValue == RevealValue.Revealed) {
-            onFullSwipe()
+        val swipeCompleted by remember {
+            derivedStateOf { state.currentValue == RevealValue.Revealed }
+        }
+        val density = LocalDensity.current
+
+        // Total width available for the slot(s) based on the current swipe offset
+        val availableWidth = if (state.offset.isNaN()) 0.dp
+        else with(density) { abs(state.offset).toDp() }
+
+        Row(
+            modifier = Modifier.matchParentSize(),
+            horizontalArrangement = Arrangement.Absolute.Right
+        ) {
+            if (swipeCompleted && undoAction != null) {
+                Row(
+                    modifier = Modifier.fillMaxWidth(),
+                    horizontalArrangement = Arrangement.Center
+                ) {
+                    ActionSlot(revealScope, content = undoAction)
+                }
+            } else {
+                Row(
+                    modifier = Modifier.width(availableWidth),
+                    horizontalArrangement = Arrangement.Absolute.Right
+                ) {
+                    if (additionalAction != null &&
+                        abs(state.offset) <= revealScope.revealOffset) {
+                        Spacer(Modifier.size(SwipeToRevealDefaults.padding))
+                        ActionSlot(revealScope, content = additionalAction)
+                    }
+                    Spacer(Modifier.size(SwipeToRevealDefaults.padding))
+                    ActionSlot(revealScope, content = action)
+                }
+            }
+        }
+        Row(
+            modifier = Modifier.absoluteOffset {
+                IntOffset(
+                    x = state.requireOffset().roundToInt().coerceAtMost(0),
+                    y = 0
+                )
+            }
+        ) {
+            content()
+        }
+        LaunchedEffect(state.currentValue) {
+            if (state.currentValue == RevealValue.Revealed) {
+                onFullSwipe()
+            }
         }
     }
 }
 
+@ExperimentalWearFoundationApi
+public interface RevealScope {
+
+    /**
+     * The offset, in pixels, where the revealed actions are fully visible but the existing content
+     * would be left in place if the reveal action was stopped. This offset is used to create the
+     * anchor for [RevealValue.Revealing].
+     * If there is no such anchor defined for [RevealValue.Revealing], it returns 0.0f.
+     */
+    public val revealOffset: Float
+}
+
+@OptIn(ExperimentalWearFoundationApi::class)
+private class RevealScopeImpl constructor(
+    private val revealState: RevealState
+) : RevealScope {
+
+    /**
+     * The total width of the overlay content in float.
+     */
+    val width = mutableStateOf(0.0f)
+
+    override val revealOffset: Float
+        get() = width.value * (revealState.swipeAnchors[RevealValue.Revealing] ?: 0.0f)
+}
+
 /**
  * An internal object containing some defaults used across the Swipe to reveal component.
  */
@@ -343,15 +381,19 @@
     internal fun defaultThreshold() = fractionalPositionalThreshold(threshold)
 }
 
+@OptIn(ExperimentalWearFoundationApi::class)
 @Composable
 private fun RowScope.ActionSlot(
+    revealScope: RevealScope,
     modifier: Modifier = Modifier,
-    content: @Composable () -> Unit
+    content: @Composable RevealScope.() -> Unit
 ) {
     Box(
         modifier = modifier.fillMaxHeight().weight(1f),
         contentAlignment = Alignment.Center
     ) {
-        content()
+        with(revealScope) {
+            content()
+        }
     }
 }
\ No newline at end of file
diff --git a/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt b/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt
index 0d57a82..31de3b4 100644
--- a/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt
+++ b/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt
@@ -124,6 +124,8 @@
                 scrollBy(value - lastValue)
                 lastValue = value
             }
+            // We consider all velocity consumed
+            return 0.0f
         }
 
         return animationState.velocity
diff --git a/wear/compose/compose-material-core/src/androidAndroidTest/kotlin/androidx/wear/compose/materialcore/ButtonTest.kt b/wear/compose/compose-material-core/src/androidAndroidTest/kotlin/androidx/wear/compose/materialcore/ButtonTest.kt
index 32c9176..167a921 100644
--- a/wear/compose/compose-material-core/src/androidAndroidTest/kotlin/androidx/wear/compose/materialcore/ButtonTest.kt
+++ b/wear/compose/compose-material-core/src/androidAndroidTest/kotlin/androidx/wear/compose/materialcore/ButtonTest.kt
@@ -30,15 +30,12 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.State
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.graphics.painter.ColorPainter
-import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.SemanticsProperties
@@ -343,11 +340,9 @@
                     .background(testBackground)
             ) {
                 ButtonWithDefaults(
-                    background = { enabled ->
+                    backgroundColor = { enabled ->
                         rememberUpdatedState(
-                            ColorPainter(
-                                if (enabled) enabledBackgroundColor else disabledBackgroundColor
-                            )
+                            if (enabled) enabledBackgroundColor else disabledBackgroundColor
                         )
                     },
                     border = { enabled ->
@@ -404,8 +399,8 @@
         modifier: Modifier = Modifier,
         onClick: () -> Unit = {},
         enabled: Boolean = true,
-        background: @Composable (enabled: Boolean) -> State<Painter> = {
-            remember { mutableStateOf(ColorPainter(DEFAULT_SHAPE_COLOR)) }
+        backgroundColor: @Composable (enabled: Boolean) -> State<Color> = {
+            rememberUpdatedState(DEFAULT_SHAPE_COLOR)
         },
         interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
         shape: Shape = CircleShape,
@@ -415,7 +410,7 @@
         onClick = onClick,
         modifier = modifier,
         enabled = enabled,
-        background = background,
+        backgroundColor = backgroundColor,
         interactionSource = interactionSource,
         shape = shape,
         border = border,
diff --git a/wear/compose/compose-material-core/src/commonMain/kotlin/androidx/wear/compose/materialcore/Button.kt b/wear/compose/compose-material-core/src/commonMain/kotlin/androidx/wear/compose/materialcore/Button.kt
index d7a5406..67e06e3 100644
--- a/wear/compose/compose-material-core/src/commonMain/kotlin/androidx/wear/compose/materialcore/Button.kt
+++ b/wear/compose/compose-material-core/src/commonMain/kotlin/androidx/wear/compose/materialcore/Button.kt
@@ -17,6 +17,7 @@
 
 import androidx.annotation.RestrictTo
 import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.Interaction
@@ -30,10 +31,8 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
-import androidx.compose.ui.draw.paint
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.painter.Painter
-import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.unit.Dp
 
@@ -50,7 +49,7 @@
  * @param modifier Modifier to be applied to the button.
  * @param enabled Controls the enabled state of the button. When `false`, this button will not
  * be clickable.
- * @param background Resolves the background for this button in different states.
+ * @param backgroundColor Resolves the background for this button in different states.
  * @param interactionSource The [MutableInteractionSource] representing the stream of
  * [Interaction]s for this Button. You can create and pass in your own remembered
  * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
@@ -67,7 +66,7 @@
     onClick: () -> Unit,
     modifier: Modifier,
     enabled: Boolean,
-    background: @Composable (enabled: Boolean) -> State<Painter>,
+    backgroundColor: @Composable (enabled: Boolean) -> State<Color>,
     interactionSource: MutableInteractionSource,
     shape: Shape,
     border: @Composable (enabled: Boolean) -> State<BorderStroke?>?,
@@ -93,13 +92,13 @@
             )
             .size(buttonSize)
             .clip(shape) // Clip for the painted background area after size has been applied.
-            .paint(
-                painter = background(enabled).value,
-                contentScale = ContentScale.Crop
-            )
             .then(
                 if (borderStroke != null) Modifier.border(border = borderStroke, shape = shape)
                 else Modifier
+            )
+            .background(
+                color = backgroundColor(enabled).value,
+                shape = shape
             ),
         content = content
     )
diff --git a/wear/compose/compose-material/api/public_plus_experimental_current.txt b/wear/compose/compose-material/api/public_plus_experimental_current.txt
index fb0f899..02e12cd 100644
--- a/wear/compose/compose-material/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-material/api/public_plus_experimental_current.txt
@@ -706,7 +706,7 @@
     method public final androidx.compose.runtime.State<java.lang.Float> getOffset();
     method public final androidx.compose.runtime.State<java.lang.Float> getOverflow();
     method public final androidx.wear.compose.material.SwipeProgress<T> getProgress();
-    method public final T! getTargetValue();
+    method public final T getTargetValue();
     method public final boolean isAnimationRunning();
     method @androidx.wear.compose.material.ExperimentalWearMaterialApi public final suspend Object? performFling(float velocity, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method @androidx.wear.compose.material.ExperimentalWearMaterialApi public final suspend Object? snapTo(T targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
@@ -716,7 +716,7 @@
     property @androidx.wear.compose.material.ExperimentalWearMaterialApi public final androidx.compose.runtime.State<java.lang.Float> offset;
     property @androidx.wear.compose.material.ExperimentalWearMaterialApi public final androidx.compose.runtime.State<java.lang.Float> overflow;
     property @androidx.wear.compose.material.ExperimentalWearMaterialApi public final androidx.wear.compose.material.SwipeProgress<T> progress;
-    property @androidx.wear.compose.material.ExperimentalWearMaterialApi public final T! targetValue;
+    property @androidx.wear.compose.material.ExperimentalWearMaterialApi public final T targetValue;
     field public static final androidx.wear.compose.material.SwipeableState.Companion Companion;
   }
 
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Button.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Button.kt
index d84fbcb..b298e04 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Button.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Button.kt
@@ -31,7 +31,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.painter.ColorPainter
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 
@@ -159,7 +158,7 @@
         onClick = onClick,
         modifier = modifier,
         enabled = enabled,
-        background = { rememberUpdatedState(ColorPainter(colors.backgroundColor(it).value)) },
+        backgroundColor = { colors.backgroundColor(it) },
         interactionSource = interactionSource,
         shape = shape,
         border = { border.borderStroke(enabled = it) },
@@ -341,7 +340,7 @@
             .padding(backgroundPadding)
             .requiredSize(ButtonDefaults.ExtraSmallButtonSize),
         enabled = enabled,
-        background = { rememberUpdatedState(ColorPainter(colors.backgroundColor(it).value)) },
+        backgroundColor = { colors.backgroundColor(it) },
         interactionSource = interactionSource,
         shape = shape,
         border = { border.borderStroke(it) },
diff --git a/wear/compose/compose-material3/api/current.txt b/wear/compose/compose-material3/api/current.txt
index ccd81a2..cf3b196 100644
--- a/wear/compose/compose-material3/api/current.txt
+++ b/wear/compose/compose-material3/api/current.txt
@@ -115,12 +115,52 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
   }
 
+  @androidx.compose.runtime.Immutable public final class IconButtonColors {
+  }
+
+  public final class IconButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors filledIconButtonColors(optional long containerColor, optional long contentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors filledTonalIconButtonColors(optional long containerColor, optional long contentColor);
+    method public float getDefaultButtonSize();
+    method public float getDefaultIconSize();
+    method public float getExtraSmallButtonSize();
+    method public float getLargeButtonSize();
+    method public float getLargeIconSize();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getShape();
+    method public float getSmallButtonSize();
+    method public float getSmallIconSize();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method public float iconSizeFor(float size);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke outlinedIconButtonBorder(boolean enabled, optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors(optional long contentColor);
+    property public final float DefaultButtonSize;
+    property public final float DefaultIconSize;
+    property public final float ExtraSmallButtonSize;
+    property public final float LargeButtonSize;
+    property public final float LargeIconSize;
+    property public final float SmallButtonSize;
+    property public final float SmallIconSize;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape shape;
+    field public static final androidx.wear.compose.material3.IconButtonDefaults INSTANCE;
+  }
+
+  public final class IconButtonKt {
+    method @androidx.compose.runtime.Composable public static void FilledIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class IconKt {
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
+  public final class InteractiveComponentSizeKt {
+    method public static androidx.compose.ui.Modifier minimumInteractiveComponentSize(androidx.compose.ui.Modifier);
+  }
+
   public final class MaterialTheme {
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.ColorScheme getColorScheme();
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Shapes getShapes();
@@ -180,6 +220,10 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
   }
 
+  public final class TouchTargetAwareSizeKt {
+    method public static androidx.compose.ui.Modifier touchTargetAwareSize(androidx.compose.ui.Modifier, float size);
+  }
+
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle displayExtraLarge, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
     method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayExtraLarge, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
diff --git a/wear/compose/compose-material3/api/public_plus_experimental_current.txt b/wear/compose/compose-material3/api/public_plus_experimental_current.txt
index ccd81a2..a23926c 100644
--- a/wear/compose/compose-material3/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-material3/api/public_plus_experimental_current.txt
@@ -115,12 +115,57 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
   }
 
+  @kotlin.RequiresOptIn(message="This Wear Material3 API is experimental and is likely to change or to be removed in" + " the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalWearMaterial3Api {
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconButtonColors {
+  }
+
+  public final class IconButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors filledIconButtonColors(optional long containerColor, optional long contentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors filledTonalIconButtonColors(optional long containerColor, optional long contentColor);
+    method public float getDefaultButtonSize();
+    method public float getDefaultIconSize();
+    method public float getExtraSmallButtonSize();
+    method public float getLargeButtonSize();
+    method public float getLargeIconSize();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getShape();
+    method public float getSmallButtonSize();
+    method public float getSmallIconSize();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method public float iconSizeFor(float size);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke outlinedIconButtonBorder(boolean enabled, optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors(optional long contentColor);
+    property public final float DefaultButtonSize;
+    property public final float DefaultIconSize;
+    property public final float ExtraSmallButtonSize;
+    property public final float LargeButtonSize;
+    property public final float LargeIconSize;
+    property public final float SmallButtonSize;
+    property public final float SmallIconSize;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape shape;
+    field public static final androidx.wear.compose.material3.IconButtonDefaults INSTANCE;
+  }
+
+  public final class IconButtonKt {
+    method @androidx.compose.runtime.Composable public static void FilledIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class IconKt {
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
+  public final class InteractiveComponentSizeKt {
+    method @androidx.wear.compose.material3.ExperimentalWearMaterial3Api public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Boolean> getLocalMinimumInteractiveComponentEnforcement();
+    method public static androidx.compose.ui.Modifier minimumInteractiveComponentSize(androidx.compose.ui.Modifier);
+    property @androidx.wear.compose.material3.ExperimentalWearMaterial3Api public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Boolean> LocalMinimumInteractiveComponentEnforcement;
+  }
+
   public final class MaterialTheme {
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.ColorScheme getColorScheme();
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Shapes getShapes();
@@ -180,6 +225,10 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
   }
 
+  public final class TouchTargetAwareSizeKt {
+    method public static androidx.compose.ui.Modifier touchTargetAwareSize(androidx.compose.ui.Modifier, float size);
+  }
+
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle displayExtraLarge, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
     method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayExtraLarge, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
diff --git a/wear/compose/compose-material3/api/restricted_current.txt b/wear/compose/compose-material3/api/restricted_current.txt
index ccd81a2..cf3b196 100644
--- a/wear/compose/compose-material3/api/restricted_current.txt
+++ b/wear/compose/compose-material3/api/restricted_current.txt
@@ -115,12 +115,52 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
   }
 
+  @androidx.compose.runtime.Immutable public final class IconButtonColors {
+  }
+
+  public final class IconButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors filledIconButtonColors(optional long containerColor, optional long contentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors filledTonalIconButtonColors(optional long containerColor, optional long contentColor);
+    method public float getDefaultButtonSize();
+    method public float getDefaultIconSize();
+    method public float getExtraSmallButtonSize();
+    method public float getLargeButtonSize();
+    method public float getLargeIconSize();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getShape();
+    method public float getSmallButtonSize();
+    method public float getSmallIconSize();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method public float iconSizeFor(float size);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke outlinedIconButtonBorder(boolean enabled, optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors(optional long contentColor);
+    property public final float DefaultButtonSize;
+    property public final float DefaultIconSize;
+    property public final float ExtraSmallButtonSize;
+    property public final float LargeButtonSize;
+    property public final float LargeIconSize;
+    property public final float SmallButtonSize;
+    property public final float SmallIconSize;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape shape;
+    field public static final androidx.wear.compose.material3.IconButtonDefaults INSTANCE;
+  }
+
+  public final class IconButtonKt {
+    method @androidx.compose.runtime.Composable public static void FilledIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class IconKt {
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
+  public final class InteractiveComponentSizeKt {
+    method public static androidx.compose.ui.Modifier minimumInteractiveComponentSize(androidx.compose.ui.Modifier);
+  }
+
   public final class MaterialTheme {
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.ColorScheme getColorScheme();
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Shapes getShapes();
@@ -180,6 +220,10 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
   }
 
+  public final class TouchTargetAwareSizeKt {
+    method public static androidx.compose.ui.Modifier touchTargetAwareSize(androidx.compose.ui.Modifier, float size);
+  }
+
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle displayExtraLarge, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
     method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayExtraLarge, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
diff --git a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
index ede1df5..58f7beb 100644
--- a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
@@ -354,7 +354,7 @@
             status = Status.Disabled,
             colors = { ButtonDefaults.filledButtonColors() },
             expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
-                alpha = DisabledContainerAlpha
+                alpha = DisabledBorderAndContainerAlpha
             ) },
             expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
                 alpha = ContentAlpha.disabled
@@ -380,7 +380,7 @@
             status = Status.Disabled,
             colors = { ButtonDefaults.filledTonalButtonColors() },
             expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
-                alpha = DisabledContainerAlpha
+                alpha = DisabledBorderAndContainerAlpha
             ) },
             expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
                 alpha = ContentAlpha.disabled
@@ -430,7 +430,7 @@
             status = Status.Disabled,
             colors = { ButtonDefaults.childButtonColors() },
             expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
-                alpha = DisabledContainerAlpha
+                alpha = DisabledBorderAndContainerAlpha
             ) },
             expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
                 alpha = ContentAlpha.disabled
@@ -689,7 +689,7 @@
 }
 
 @RequiresApi(Build.VERSION_CODES.O)
-internal fun ComposeContentTestRule.isShape(
+private fun ComposeContentTestRule.isShape(
     expectedShape: Shape,
     colors: @Composable () -> ButtonColors,
     content: @Composable (Modifier) -> Unit
@@ -726,4 +726,4 @@
         )
 }
 
-const val DisabledContainerAlpha = 0.12f
\ No newline at end of file
+val MinimumButtonTapSize = 48.dp
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
new file mode 100644
index 0000000..d12eb43
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
@@ -0,0 +1,497 @@
+/*
+ * 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.wear.compose.material3
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.CutCornerShape
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.assertShape
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.assertIsEnabled
+import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material3.IconButtonDefaults.DefaultButtonSize
+import androidx.wear.compose.material3.IconButtonDefaults.ExtraSmallButtonSize
+import androidx.wear.compose.material3.IconButtonDefaults.LargeButtonSize
+import androidx.wear.compose.material3.IconButtonDefaults.SmallButtonSize
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+
+class IconButtonTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun supports_testtag() {
+        rule.setContentWithTheme {
+            IconButton(
+                modifier = Modifier.testTag(TEST_TAG),
+                onClick = {}
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun has_click_action_when_enabled() {
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = {},
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
+    }
+
+    @Test
+    fun has_click_action_when_disabled() {
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = {},
+                enabled = false,
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
+    }
+
+    @Test
+    fun is_correctly_enabled() {
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = {},
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
+    }
+
+    @Test
+    fun is_correctly_disabled() {
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = {},
+                enabled = false,
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
+    }
+
+    @Test
+    fun responds_to_click_when_enabled() {
+        var clicked = false
+
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = { clicked = true },
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).performClick()
+
+        rule.runOnIdle {
+            assertEquals(true, clicked)
+        }
+    }
+
+    @Test
+    fun does_not_respond_to_click_when_disabled() {
+        var clicked = false
+
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = { clicked = true },
+                enabled = false,
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).performClick()
+
+        rule.runOnIdle {
+            assertEquals(false, clicked)
+        }
+    }
+
+    @Test
+    fun has_role_button() {
+        rule.setContentWithTheme {
+            IconButton(
+                onClick = {},
+                modifier = Modifier.testTag(TEST_TAG)
+            ) {
+                TestImage()
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG)
+            .assert(
+                SemanticsMatcher.expectValue(
+                    SemanticsProperties.Role,
+                    Role.Button
+                )
+            )
+    }
+
+    @Test
+    fun gives_default_button_correct_tap_size() {
+        rule.verifyTapSize(DefaultButtonSize) { modifier ->
+            IconButton(
+                onClick = {},
+                modifier = modifier.touchTargetAwareSize(DefaultButtonSize)
+            ) {
+                TestImage()
+            }
+        }
+    }
+
+    @Test
+    fun gives_large_button_correct_tap_size() {
+        rule.verifyTapSize(LargeButtonSize) { modifier ->
+            IconButton(
+                onClick = {},
+                modifier = modifier.touchTargetAwareSize(LargeButtonSize)
+            ) {
+                TestImage()
+            }
+        }
+    }
+
+    @Test
+    fun gives_small_button_correct_tap_size() {
+        rule.verifyTapSize(SmallButtonSize) { modifier ->
+            IconButton(
+                onClick = {},
+                modifier = modifier.touchTargetAwareSize(SmallButtonSize)
+            ) {
+                TestImage()
+            }
+        }
+    }
+
+    @Test
+    fun gives_extra_small_button_correct_tap_size() {
+        rule.verifyTapSize(
+            expectedSize = MinimumButtonTapSize
+        ) { modifier ->
+            IconButton(
+                onClick = {},
+                modifier = modifier.touchTargetAwareSize(ExtraSmallButtonSize)
+            ) {
+                TestImage()
+            }
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun default_shape_is_circular() {
+        rule.isShape(
+            expectedShape = CircleShape,
+            colors = { IconButtonDefaults.iconButtonColors() }
+        ) { modifier ->
+            IconButton(
+                onClick = {},
+                modifier = modifier
+            ) {
+                // omit content to allow us to validate the shape by pixel checking.
+            }
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun allows_custom_shape_override() {
+        val shape = CutCornerShape(4.dp)
+
+        rule.isShape(
+            expectedShape = shape,
+            colors = { IconButtonDefaults.iconButtonColors() }
+        ) { modifier ->
+            IconButton(
+                onClick = {},
+                modifier = modifier,
+                shape = shape
+            ) {
+                // omit content to allow us to validate the shape by pixel checking.
+            }
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_enabled_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Enabled,
+            colors = { IconButtonDefaults.iconButtonColors() },
+            expectedContainerColor = { Color.Transparent },
+            expectedContentColor = { MaterialTheme.colorScheme.onBackground }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_disabled_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Disabled,
+            colors = { IconButtonDefaults.iconButtonColors() },
+            expectedContainerColor = { Color.Transparent },
+            expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
+                alpha = ContentAlpha.disabled
+            ) }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_enabled_filled_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Enabled,
+            colors = { IconButtonDefaults.filledIconButtonColors() },
+            expectedContainerColor = { MaterialTheme.colorScheme.primary },
+            expectedContentColor = { MaterialTheme.colorScheme.onPrimary }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_disabled_filled_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Disabled,
+            colors = { IconButtonDefaults.filledIconButtonColors() },
+            expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
+                alpha = DisabledBorderAndContainerAlpha
+            ) },
+            expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
+                alpha = ContentAlpha.disabled
+            ) }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_enabled_filled_tonal_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Enabled,
+            colors = { IconButtonDefaults.filledTonalIconButtonColors() },
+            expectedContainerColor = { MaterialTheme.colorScheme.surface },
+            expectedContentColor = { MaterialTheme.colorScheme.onSurfaceVariant }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_disabled_filled_tonal_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Disabled,
+            colors = { IconButtonDefaults.filledTonalIconButtonColors() },
+            expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
+                alpha = DisabledBorderAndContainerAlpha
+            ) },
+            expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
+                alpha = ContentAlpha.disabled
+            ) }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_enabled_outlined_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Enabled,
+            colors = { IconButtonDefaults.outlinedIconButtonColors() },
+            expectedContainerColor = { Color.Transparent },
+            expectedContentColor = { MaterialTheme.colorScheme.primary }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_disabled_outlined_icon_button_colors() {
+        rule.verifyIconButtonColors(
+            status = Status.Disabled,
+            colors = { IconButtonDefaults.outlinedIconButtonColors() },
+            expectedContainerColor = { Color.Transparent },
+            expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
+                alpha = ContentAlpha.disabled
+            ) }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_enabled_outlined_icon_button_correct_border_colors() {
+        val status = Status.Enabled
+        rule.verifyButtonBorderColor(
+            expectedBorderColor = { MaterialTheme.colorScheme.outline },
+            content = { modifier: Modifier ->
+                OutlinedIconButton(
+                    onClick = {},
+                    modifier = modifier,
+                    enabled = status.enabled()
+                ) {}
+            }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun gives_disabled_outlined_icon_button_correct_border_colors() {
+        val status = Status.Disabled
+        rule.verifyButtonBorderColor(
+            expectedBorderColor = {
+                MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledBorderAndContainerAlpha)
+            },
+            content = { modifier: Modifier ->
+                OutlinedIconButton(
+                    onClick = {},
+                    modifier = modifier,
+                    enabled = status.enabled()
+                ) {}
+            }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun overrides_outlined_icon_button_border_color() {
+        val status = Status.Enabled
+        rule.verifyButtonBorderColor(
+            expectedBorderColor = { Color.Green },
+            content = { modifier: Modifier ->
+                OutlinedIconButton(
+                    onClick = {},
+                    modifier = modifier,
+                    enabled = status.enabled(),
+                    border = ButtonDefaults.outlinedButtonBorder(
+                        enabled = status.enabled(),
+                        borderColor = Color.Green,
+                        disabledBorderColor = Color.Red
+                    )
+                ) {}
+            }
+        )
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    private fun ComposeContentTestRule.verifyIconButtonColors(
+        status: Status,
+        colors: @Composable () -> IconButtonColors,
+        expectedContainerColor: @Composable () -> Color,
+        expectedContentColor: @Composable () -> Color,
+    ) {
+        verifyColors(
+            status = status,
+            expectedContainerColor = expectedContainerColor,
+            expectedContentColor = expectedContentColor,
+            applyAlphaForDisabled = false,
+            content = {
+                var actualContentColor = Color.Transparent
+                IconButton(
+                    onClick = {},
+                    enabled = status.enabled(),
+                    colors = colors(),
+                    modifier = Modifier.testTag(TEST_TAG),
+                ) {
+                    actualContentColor = LocalContentColor.current
+                }
+                return@verifyColors actualContentColor
+            }
+        )
+    }
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+private fun ComposeContentTestRule.isShape(
+    expectedShape: Shape,
+    colors: @Composable () -> IconButtonColors,
+    content: @Composable (Modifier) -> Unit
+) {
+    var background = Color.Transparent
+    var buttonColor = Color.Transparent
+    val padding = 0.dp
+
+    setContentWithTheme {
+        background = MaterialTheme.colorScheme.surface
+        Box(Modifier.background(background)) {
+            buttonColor = colors().containerColor(true).value
+            if (buttonColor == Color.Transparent) {
+                buttonColor = background
+            }
+            content(
+                Modifier
+                    .testTag(TEST_TAG)
+                    .padding(padding)
+            )
+        }
+    }
+
+    onNodeWithTag(TEST_TAG)
+        .captureToImage()
+        .assertShape(
+            density = density,
+            horizontalPadding = 0.dp,
+            verticalPadding = 0.dp,
+            shapeColor = buttonColor,
+            backgroundColor = background,
+            shapeOverlapPixelCount = 2.0f,
+            shape = expectedShape,
+        )
+}
diff --git a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
index 6642e9a..750e25e 100644
--- a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
+++ b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
@@ -38,6 +38,8 @@
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assertTouchHeightIsEqualTo
+import androidx.compose.ui.test.assertTouchWidthIsEqualTo
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.ComposeContentTestRule
 import androidx.compose.ui.test.onNodeWithTag
@@ -121,6 +123,20 @@
     }
 }
 
+internal fun ComposeContentTestRule.verifyTapSize(
+    expectedSize: Dp,
+    content: @Composable (modifier: Modifier) -> Unit
+) {
+    setContentWithTheme {
+        content(Modifier.testTag(TEST_TAG))
+    }
+    waitForIdle()
+
+    onNodeWithTag(TEST_TAG)
+        .assertTouchHeightIsEqualTo(expectedSize)
+        .assertTouchWidthIsEqualTo(expectedSize)
+}
+
 @RequiresApi(Build.VERSION_CODES.O)
 internal fun ComposeContentTestRule.verifyColors(
     status: Status,
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt
index 8eaa073..fa6786f 100644
--- a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt
@@ -381,7 +381,7 @@
             secondaryLabel
         ) },
         icon = icon?.let {
-            provideIcon(colors.iconColor(enabled), icon)
+            provideScopeContent(colors.iconColor(enabled), icon)
         },
         defaultIconSpacing = ButtonDefaults.IconSpacing,
         role = role
@@ -917,8 +917,6 @@
      * [Button].
      */
     internal val IconSpacing = 6.dp
-
-    internal const val DisabledBorderAndContainerAlpha = 0.12f
 }
 
 /**
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt
index 91e559b..8471524 100644
--- a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt
@@ -122,3 +122,5 @@
     const val medium: Float = 0.60f
     const val disabled: Float = 0.38f
 }
+
+internal const val DisabledBorderAndContainerAlpha = 0.12f
diff --git a/car/app/app-automotive/src/main/stableAidlImports/android/view/KeyEvent.aidl b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ExperimentalWearMaterial3Api.kt
similarity index 64%
rename from car/app/app-automotive/src/main/stableAidlImports/android/view/KeyEvent.aidl
rename to wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ExperimentalWearMaterial3Api.kt
index cfaff66..1d369e6 100644
--- a/car/app/app-automotive/src/main/stableAidlImports/android/view/KeyEvent.aidl
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ExperimentalWearMaterial3Api.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,6 +14,11 @@
  * limitations under the License.
  */
 
-package android.view;
+package androidx.wear.compose.material3
 
-@JavaOnlyStableParcelable parcelable KeyEvent;
+@RequiresOptIn(
+    "This Wear Material3 API is experimental and is likely to change or to be removed in" +
+        " the future."
+)
+@Retention(AnnotationRetention.BINARY)
+annotation class ExperimentalWearMaterial3Api
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt
new file mode 100644
index 0000000..087dd93
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt
@@ -0,0 +1,472 @@
+/*
+ * 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.wear.compose.material3
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.max
+
+/**
+ * Wear Material [IconButton] is a circular, icon-only button with transparent background and
+ * no border. It offers a single slot to take icon or image content.
+ *
+ * Set the size of the [IconButton] with Modifier.[touchTargetAwareSize]
+ * to ensure that the recommended minimum touch target size is available.
+ *
+ * The recommended [IconButton] sizes are [IconButtonDefaults.DefaultButtonSize],
+ * [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
+ * [IconButtonDefaults.ExtraSmallButtonSize].
+ *
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
+ * given [IconButtonDefaults] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeButtonSize] directly.
+ *
+ * [IconButton] can be enabled or disabled. A disabled button will not respond to click events.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
+ *
+ * @param onClick Will be called when the user clicks the button.
+ * @param modifier Modifier to be applied to the button.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not
+ * be clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default
+ * as this shape is a key characteristic of the Wear Material3 design.
+ * @param colors [IconButtonColors] that will be used to resolve the background and icon color for
+ * this button in different states.
+ * @param border Optional [BorderStroke] for the icon button border.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this Button. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this Button in different [Interaction]s.
+ * @param content The content displayed on the icon button, expected to be icon or image.
+ */
+@Composable
+fun IconButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    shape: Shape = IconButtonDefaults.shape,
+    colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
+    border: BorderStroke? = null,
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    content: @Composable BoxScope.() -> Unit,
+) {
+    androidx.wear.compose.materialcore.Button(
+        onClick = onClick,
+        modifier.minimumInteractiveComponentSize(),
+        enabled = enabled,
+        backgroundColor = { colors.containerColor(enabled = it) },
+        interactionSource = interactionSource,
+        shape = shape,
+        border = { rememberUpdatedState(border) },
+        buttonSize = IconButtonDefaults.DefaultButtonSize,
+        content = provideScopeContent(
+            colors.contentColor(enabled = enabled),
+            content
+        )
+    )
+}
+
+/**
+ * Wear Material [FilledIconButton] is a circular, icon-only button with a colored background
+ * and a contrasting content color. It offers a single slot to take an icon or image.
+ *
+ * Set the size of the [FilledIconButton] with Modifier.[touchTargetAwareSize]
+ * to ensure that the recommended minimum touch target size is available.
+ *
+ * The recommended [IconButton] sizes are [IconButtonDefaults.DefaultButtonSize],
+ * [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
+ * [IconButtonDefaults.ExtraSmallButtonSize].
+ *
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
+ * given [IconButton] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeIconSize] directly.
+ *
+ * [FilledIconButton] can be enabled or disabled. A disabled button will not respond to
+ * click events.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
+ *
+ * @param onClick Will be called when the user clicks the button.
+ * @param modifier Modifier to be applied to the button.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not
+ * be clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default
+ * as this shape is a key characteristic of the Wear Material3 design.
+ * @param colors [IconButtonColors] that will be used to resolve the container and content color for
+ * this icon button in different states.
+ * @param border Optional [BorderStroke] for the icon button border.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this Button. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this Button in different [Interaction]s.
+ * @param content The content displayed on the icon button, expected to be icon or image.
+ */
+@Composable
+fun FilledIconButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    shape: Shape = IconButtonDefaults.shape,
+    colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors(),
+    border: BorderStroke? = null,
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    content: @Composable BoxScope.() -> Unit,
+) = IconButton(onClick, modifier, enabled, shape, colors, border, interactionSource, content)
+
+/**
+ * Wear Material [FilledTonalIconButton] is a circular, icon-only button with a muted, colored
+ * background and a contrasting icon color. It offers a single slot to take an icon or image.
+ *
+ * Set the size of the [FilledTonalIconButton] with Modifier.[touchTargetAwareSize]
+ * to ensure that the recommended minimum touch target size is available.
+ *
+ * The recommended icon button sizes are [IconButtonDefaults.DefaultButtonSize],
+ * [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
+ * [IconButtonDefaults.ExtraSmallButtonSize].
+ *
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
+ * given [IconButtonDefaults] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeButtonSize] directly.
+ *
+ * [FilledTonalIconButton] can be enabled or disabled.
+ * A disabled button will not respond to click events.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
+ *
+ * @param onClick Will be called when the user clicks the button.
+ * @param modifier Modifier to be applied to the button.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not
+ * be clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default
+ * as this shape is a key characteristic of the Wear Material3 design.
+ * @param colors [IconButtonColors] that will be used to resolve the background and icon color for
+ * this button in different states.
+ * @param border Optional [BorderStroke] for the icon button border.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this Button. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this Button in different [Interaction]s.
+ * @param content The content displayed on the icon button, expected to be icon or image.
+ */
+@Composable
+fun FilledTonalIconButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    shape: Shape = IconButtonDefaults.shape,
+    colors: IconButtonColors = IconButtonDefaults.filledTonalIconButtonColors(),
+    border: BorderStroke? = null,
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    content: @Composable BoxScope.() -> Unit,
+) = IconButton(onClick, modifier, enabled, shape, colors, border, interactionSource, content)
+
+/**
+ * Wear Material [OutlinedIconButton] is a circular, icon-only button with a transparent background,
+ * contrasting icon color and border. It offers a single slot to take an icon or image.
+ *
+ * Set the size of the [OutlinedIconButton] with Modifier.[touchTargetAwareSize]
+ * to ensure that the recommended minimum touch target size is available.
+ *
+ * The recommended icon button sizes are [IconButtonDefaults.DefaultButtonSize],
+ * [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
+ * [IconButtonDefaults.ExtraSmallButtonSize].
+ *
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
+ * given [IconButtonDefaults] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeButtonSize] directly.
+ *
+ * [OutlinedIconButton] can be enabled or disabled.
+ * A disabled button will not respond to click events.
+ *
+ * An [OutlinedIconButton] has a transparent background and a thin border by default with
+ * content taking the theme primary color.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
+ *
+ * @param onClick Will be called when the user clicks the button.
+ * @param modifier Modifier to be applied to the button.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not
+ * be clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default
+ * as this shape is a key characteristic of the Wear Material3 design.
+ * @param colors [IconButtonColors] that will be used to resolve the background and icon color for
+ * this button in different states. See [IconButtonDefaults.outlinedIconButtonBorder].
+ * @param border Optional [BorderStroke] for the icon button border.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this Button. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this Button in different [Interaction]s.
+ * @param content The content displayed on the icon button, expected to be icon or image.
+ */
+@Composable
+fun OutlinedIconButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    shape: Shape = IconButtonDefaults.shape,
+    colors: IconButtonColors = IconButtonDefaults.outlinedIconButtonColors(),
+    border: BorderStroke? = IconButtonDefaults.outlinedIconButtonBorder(enabled),
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    content: @Composable BoxScope.() -> Unit,
+) = IconButton(onClick, modifier, enabled, shape, colors, border, interactionSource, content)
+
+/**
+ * Contains the default values used by [IconButton].
+ */
+object IconButtonDefaults {
+    /**
+     * Recommended [Shape] for [IconButton].
+     */
+    val shape = CircleShape
+
+    /**
+     * Recommended icon size for a given icon button size.
+     *
+     * Ensures that the minimum recommended icon size is applied.
+     *
+     * Examples: for size [LargeButtonSize], returns [LargeIconSize],
+     * for size [ExtraSmallButtonSize] returns [SmallIconSize].
+     *
+     * @param size The size of the icon button
+     */
+    fun iconSizeFor(size: Dp): Dp = max(SmallIconSize, size / 2f)
+
+    /**
+     * Creates a [ButtonColors] with the colors for [FilledIconButton] - by default,
+     * a colored background with a contrasting icon color.
+     * If the icon button is disabled then the colors will default to
+     * the MaterialTheme onSurface color with suitable alpha values applied.
+     *
+     * @param containerColor The background color of this icon button when enabled
+     * @param contentColor The color of this icon button when enabled
+     */
+    @Composable
+    fun filledIconButtonColors(
+        containerColor: Color = MaterialTheme.colorScheme.primary,
+        contentColor: Color = MaterialTheme.colorScheme.onPrimary,
+    ): IconButtonColors {
+        return iconButtonColors(
+            containerColor = containerColor,
+            contentColor = contentColor
+        )
+    }
+
+    /**
+     * Creates a [ButtonColors] with the colors for [FilledTonalIconButton]- by default,
+     * a muted colored background with a contrasting icon color.
+     * If the icon button is disabled then the colors will default to
+     * the MaterialTheme onSurface color with suitable alpha values applied.
+     *
+     * @param containerColor The background color of this icon button when enabled
+     * @param contentColor The color of this icon button when enabled
+     */
+    @Composable
+    fun filledTonalIconButtonColors(
+        containerColor: Color = MaterialTheme.colorScheme.surface,
+        contentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
+    ): IconButtonColors {
+        return iconButtonColors(
+            containerColor = containerColor,
+            contentColor = contentColor
+        )
+    }
+
+    /**
+     * Creates a [ButtonColors] with the colors for [OutlinedIconButton]- by default,
+     * a transparent background with contrasting icon color.
+     * If the icon button is disabled then the colors will default to
+     * the MaterialTheme onSurface color with suitable alpha values applied.
+     *
+     * @param contentColor The color of this icon button when enabled
+     */
+    @Composable
+    fun outlinedIconButtonColors(
+        contentColor: Color = MaterialTheme.colorScheme.primary,
+    ): IconButtonColors {
+        return iconButtonColors(
+            containerColor = Color.Transparent,
+            contentColor = contentColor
+        )
+    }
+
+    /**
+     * Creates a [ButtonColors] with the colors for [IconButton] - by default,
+     * a transparent background with a contrasting icon color.
+     * If the icon button is disabled then the colors will default to
+     * the MaterialTheme onSurface color with suitable alpha values applied.
+     *
+     * @param containerColor the background color of this icon button when enabled
+     * @param contentColor the color of this icon when enabled
+     * @param disabledContainerColor the background color of this icon button when not enabled
+     * @param disabledContentColor the color of this icon when not enabled
+     */
+    @Composable
+    fun iconButtonColors(
+        containerColor: Color = Color.Transparent,
+        contentColor: Color = MaterialTheme.colorScheme.onBackground,
+        disabledContainerColor: Color = MaterialTheme.colorScheme.onSurface.copy(
+            alpha = DisabledBorderAndContainerAlpha
+        ),
+        disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.copy(
+            alpha = ContentAlpha.disabled
+        )
+    ): IconButtonColors = IconButtonColors(
+        containerColor = containerColor,
+        contentColor = contentColor,
+        disabledContainerColor = disabledContainerColor,
+        disabledContentColor = disabledContentColor,
+    )
+
+    /**
+     * Creates a [BorderStroke], such as for an [OutlinedIconButton]
+     *
+     * @param borderColor The color to use for the border for this outline when enabled
+     * @param disabledBorderColor The color to use for the border for this outline when
+     * disabled
+     * @param borderWidth The width to use for the border for this outline. It is strongly
+     * recommended to use the default width as this outline is a key characteristic
+     * of Wear Material3.
+     */
+    @Composable
+    fun outlinedIconButtonBorder(
+        enabled: Boolean,
+        borderColor: Color = MaterialTheme.colorScheme.outline,
+        disabledBorderColor: Color = MaterialTheme.colorScheme.onSurface.copy(
+            alpha = DisabledBorderAndContainerAlpha
+        ),
+        borderWidth: Dp = 1.dp
+    ): BorderStroke {
+        return remember {
+            BorderStroke(borderWidth, if (enabled) borderColor else disabledBorderColor)
+        }
+    }
+
+    /**
+     * The recommended size of an icon when used inside an icon button with size
+     * [SmallButtonSize] or [ExtraSmallButtonSize].
+     * Use [iconSizeFor] to easily determine the icon size.
+     */
+    val SmallIconSize = 24.dp
+
+    /**
+     * The default size of an icon when used inside an icon button of size DefaultButtonSize.
+     * Use [iconSizeFor] to easily determine the icon size.
+     */
+    val DefaultIconSize = 26.dp
+
+    /**
+     * The size of an icon when used inside an icon button with size [LargeButtonSize].
+     * Use [iconSizeFor] to easily determine the icon size.
+     */
+    val LargeIconSize = 30.dp
+
+    /**
+     * The recommended background size of an extra small, compact button.
+     * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+     */
+    val ExtraSmallButtonSize = 32.dp
+
+    /**
+     * The recommended size for a small button.
+     * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+     */
+    val SmallButtonSize = 48.dp
+
+    /**
+     * The default size applied for buttons.
+     * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+     */
+    val DefaultButtonSize = 52.dp
+
+    /**
+     * The recommended size for a large button.
+     * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+     */
+    val LargeButtonSize = 60.dp
+}
+
+/**
+ * Represents the container and content colors used in an icon button in different states.
+ *
+ * - See [IconButtonDefaults.filledIconButtonColors] and
+ * [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a
+ * [FilledIconButton].
+ * - See [IconButtonDefaults.outlinedIconButtonColors] for the default colors used in an
+ * [OutlinedIconButton].
+ */
+@Immutable
+class IconButtonColors internal constructor(
+    private val containerColor: Color,
+    private val contentColor: Color,
+    private val disabledContainerColor: Color,
+    private val disabledContentColor: Color,
+) {
+    /**
+     * Represents the container color for this icon button, depending on [enabled].
+     *
+     * @param enabled whether the icon button is enabled
+     */
+    @Composable
+    internal fun containerColor(enabled: Boolean): State<Color> {
+        return rememberUpdatedState(if (enabled) containerColor else disabledContainerColor)
+    }
+
+    /**
+     * Represents the content color for this icon button, depending on [enabled].
+     *
+     * @param enabled whether the icon button is enabled
+     */
+    @Composable
+    internal fun contentColor(enabled: Boolean): State<Color> {
+        return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is IconButtonColors) return false
+
+        if (containerColor != other.containerColor) return false
+        if (contentColor != other.contentColor) return false
+        if (disabledContainerColor != other.disabledContainerColor) return false
+        if (disabledContentColor != other.disabledContentColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = containerColor.hashCode()
+        result = 31 * result + contentColor.hashCode()
+        result = 31 * result + disabledContainerColor.hashCode()
+        result = 31 * result + disabledContentColor.hashCode()
+
+        return result
+    }
+}
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/InteractiveComponentSize.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/InteractiveComponentSize.kt
new file mode 100644
index 0000000..dc96844
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/InteractiveComponentSize.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.wear.compose.material3
+
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.layout.LayoutModifier
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import kotlin.math.roundToInt
+
+/**
+ * Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure
+ * smaller.
+ *
+ * https://m3.material.io/foundations/accessible-design/accessibility-basics#28032e45-c598-450c-b355-f9fe737b1cd8
+ *
+ * This uses the Material recommended minimum size of 48.dp x 48.dp, which may not the same as the
+ * system enforced minimum size.
+ *
+ * This modifier is not needed for touch target expansion to happen. It only affects layout, to make
+ * sure there is adequate space for touch target expansion.
+ */
+@OptIn(ExperimentalWearMaterial3Api::class)
+fun Modifier.minimumInteractiveComponentSize(): Modifier = composed(
+    inspectorInfo = debugInspectorInfo {
+        name = "minimumInteractiveComponentSize"
+        // TODO: b/214589635 - surface this information through the layout inspector in a better way
+        //  - for now just add some information to help developers debug what this size represents.
+        properties["README"] = "Reserves at least 48.dp in size to disambiguate touch " +
+            "interactions if the element would measure smaller"
+    }
+) {
+    if (LocalMinimumInteractiveComponentEnforcement.current) {
+        MinimumInteractiveComponentSizeModifier(minimumInteractiveComponentSize)
+    } else {
+        Modifier
+    }
+}
+
+/**
+ * CompositionLocal that configures whether Wear Material components that have a visual size that is
+ * lower than the minimum touch target size for accessibility (such as Button) will include
+ * extra space outside the component to ensure that they are accessible. If set to false there
+ * will be no extra space, and so it is possible that if the component is placed near the edge of
+ * a layout / near to another component without any padding, there will not be enough space for
+ * an accessible touch target.
+ */
+@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+@get:ExperimentalWearMaterial3Api
+@ExperimentalWearMaterial3Api
+val LocalMinimumInteractiveComponentEnforcement: ProvidableCompositionLocal<Boolean> =
+    staticCompositionLocalOf { true }
+
+private class MinimumInteractiveComponentSizeModifier(val size: DpSize) : LayoutModifier {
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints
+    ): MeasureResult {
+
+        val placeable = measurable.measure(constraints)
+
+        // Be at least as big as the minimum dimension in both dimensions
+        val width = maxOf(placeable.width, size.width.roundToPx())
+        val height = maxOf(placeable.height, size.height.roundToPx())
+
+        return layout(width, height) {
+            val centerX = ((width - placeable.width) / 2f).roundToInt()
+            val centerY = ((height - placeable.height) / 2f).roundToInt()
+            placeable.place(centerX, centerY)
+        }
+    }
+
+    override fun equals(other: Any?): Boolean {
+        val otherModifier = other as? MinimumInteractiveComponentSizeModifier ?: return false
+        return size == otherModifier.size
+    }
+
+    override fun hashCode(): Int {
+        return size.hashCode()
+    }
+}
+
+private val minimumInteractiveComponentSize: DpSize = DpSize(48.dp, 48.dp)
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Providers.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Providers.kt
index c1f9506..a8ad2b6 100644
--- a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Providers.kt
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Providers.kt
@@ -16,7 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.State
@@ -38,14 +37,13 @@
     }
 }
 
-internal fun provideIcon(
-    iconColor: State<Color>,
-    content: (@Composable BoxScope.() -> Unit)
-): (@Composable BoxScope.() -> Unit) = {
-    val color = iconColor.value
+internal fun <T> provideScopeContent(
+    color: State<Color>,
+    content: (@Composable T.() -> Unit)
+): (@Composable T.() -> Unit) = {
     CompositionLocalProvider(
-        LocalContentColor provides color,
-        LocalContentAlpha provides color.alpha,
+        LocalContentColor provides color.value,
+        LocalContentAlpha provides color.value.alpha,
     ) {
         content()
     }
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/TouchTargetAwareSize.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/TouchTargetAwareSize.kt
new file mode 100644
index 0000000..45dda91
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/TouchTargetAwareSize.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.wear.compose.material3
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.max
+
+/**
+ * Modifier to set both the size and recommended touch target for
+ * [IconButton] and TextButton.
+ */
+fun Modifier.touchTargetAwareSize(size: Dp): Modifier =
+    this
+        .padding(PaddingValues(max(0.dp, (minimumTouchTarget - size) * 0.5f)))
+        .size(size)
+
+private val minimumTouchTarget = 48.dp
diff --git a/wear/compose/compose-navigation/build.gradle b/wear/compose/compose-navigation/build.gradle
index 7bfe4ee..fc1e4dc 100644
--- a/wear/compose/compose-navigation/build.gradle
+++ b/wear/compose/compose-navigation/build.gradle
@@ -27,14 +27,14 @@
 
     api(project(":compose:ui:ui"))
     api(project(":compose:runtime:runtime"))
-    api("androidx.navigation:navigation-runtime:2.5.3")
+    api("androidx.navigation:navigation-runtime:2.6.0-beta01")
     api(project(":wear:compose:compose-material"))
     api("androidx.activity:activity-compose:1.7.0")
     api("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0")
 
     implementation(libs.kotlinStdlib)
-    implementation(project(":navigation:navigation-common"))
-    implementation("androidx.navigation:navigation-compose:2.5.3")
+    implementation("androidx.navigation:navigation-common:2.6.0-beta01")
+    implementation("androidx.navigation:navigation-compose:2.6.0-beta01")
     implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     androidTestImplementation(project(":compose:test-utils"))
@@ -45,7 +45,7 @@
     androidTestImplementation(project(":wear:compose:compose-navigation-samples"))
     androidTestImplementation(libs.truth)
     androidTestImplementation("androidx.lifecycle:lifecycle-runtime-testing:2.6.0")
-    androidTestImplementation("androidx.navigation:navigation-testing:2.5.3")
+    androidTestImplementation("androidx.navigation:navigation-testing:2.6.0-beta01")
 
     samples(project(":wear:compose:compose-navigation-samples"))
 }
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
index 57fbba0..00e8d98 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
@@ -33,6 +33,7 @@
 import androidx.wear.compose.foundation.samples.SimpleScalingLazyColumn
 import androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithContentPadding
 import androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithSnap
+import androidx.wear.compose.foundation.samples.SwipeToRevealWithExpandables
 
 val WearFoundationDemos = DemoCategory(
     "Foundation",
@@ -104,14 +105,17 @@
                 ComposableDemo("Swipe To Reveal Chip") {
                     SwipeToRevealChips()
                 },
-                ComposableDemo("Swipe to Reveal Card") {
+                ComposableDemo("Swipe To Reveal Card") {
                     SwipeToRevealCards()
                 },
-                ComposableDemo("Swipe to Reveal - Custom") {
+                ComposableDemo("Swipe To Reveal - Custom") {
                     SwipeToRevealWithSingleAction()
                 },
-                ComposableDemo("Swipe to Reveal - RTL") {
+                ComposableDemo("Swipe To Reveal - RTL") {
                     SwipeToRevealInRtl()
+                },
+                ComposableDemo("Swipe To Reveal - Expandable") {
+                    SwipeToRevealWithExpandables()
                 }
             )
         )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt
index d631e81..e0f9d24 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt
@@ -18,7 +18,9 @@
 
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -37,12 +39,14 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.wear.compose.foundation.ExpandableState
 import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
+import androidx.wear.compose.foundation.RevealScope
 import androidx.wear.compose.foundation.expandableItem
 import androidx.wear.compose.foundation.fractionalPositionalThreshold
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
@@ -58,6 +62,7 @@
 import androidx.wear.compose.material.Text
 import androidx.wear.compose.foundation.createAnchors
 import androidx.wear.compose.foundation.rememberRevealState
+import kotlin.math.abs
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
@@ -225,29 +230,35 @@
     val coroutineScope = rememberCoroutineScope()
     SwipeToReveal(
         action = {
-            DeleteButton(
-                state = state,
+            SwipeToRevealAction(
+                color = MaterialTheme.colors.error,
+                icon = Icons.Outlined.Delete,
+                text = "Clear",
+                contentDescription = "Delete",
+                onClick = { state.animateTo(RevealValue.Revealed) },
+                shape = shape,
                 coroutineScope = coroutineScope,
-                shape = shape
+                state = state
             )
         },
         additionalAction = {
-            MoreOptionsButton(
-                state = state,
+            SwipeToRevealAction(
+                color = MaterialTheme.colors.onSurfaceVariant,
+                icon = Icons.Outlined.MoreVert,
+                onClick = { state.animateTo(RevealValue.Covered) },
+                shape = shape,
                 coroutineScope = coroutineScope,
-                shape = shape
+                state = state
             )
         },
         undoAction = {
-            Box(
-                modifier = Modifier.clickable {
-                    coroutineScope.launch {
-                        state.snapTo(RevealValue.Covered)
-                    }
-                }
-            ) {
-                Text("Undo")
-            }
+            Chip(
+                modifier = Modifier.fillMaxWidth(),
+                onClick = { coroutineScope.launch { state.animateTo(RevealValue.Covered) } },
+                colors = ChipDefaults.secondaryChipColors(),
+                border = ChipDefaults.outlinedChipBorder(),
+                label = { Text(text = "Undo") }
+            )
         },
         state = state,
         content = content,
@@ -259,36 +270,54 @@
 private fun SwipeToRevealSingleAction(
     layoutDirection: LayoutDirection = LayoutDirection.Ltr
 ) {
+    val itemCount = 2
+    val expandableState = List(itemCount) {
+        rememberExpandableState(initiallyExpanded = true)
+    }
     ScalingLazyColumn {
         item {
             Text("Swipe to reveal One-Action")
             Spacer(Modifier.size(10.dp))
         }
-        repeat(2) {
-            item {
+        repeat(itemCount) { curr ->
+            expandableItem(
+                state = expandableState[curr]
+            ) { expanded ->
                 val state = rememberRevealState(
                     anchors = createAnchors(revealingAnchor = 0.5f),
                     positionalThreshold = fractionalPositionalThreshold(0.5f)
                 )
-                CompositionLocalProvider(
-                    LocalLayoutDirection provides layoutDirection
-                ) {
-                    SwipeToReveal(
-                        action = {
-                            DeleteButton(
-                                state = state,
-                                coroutineScope = rememberCoroutineScope(),
-                                shape = CircleShape
-                            )
-                        },
-                        state = state
+                if (expanded) {
+                    CompositionLocalProvider(
+                        LocalLayoutDirection provides layoutDirection
                     ) {
-                        Chip(
-                            onClick = { /*TODO*/ },
-                            colors = ChipDefaults.secondaryChipColors(),
-                            modifier = Modifier.fillMaxWidth(),
-                            label = { Text("Try this") }
-                        )
+                        SwipeToReveal(
+                            action = {
+                                SwipeToRevealAction(
+                                    color = MaterialTheme.colors.error,
+                                    icon = Icons.Outlined.Delete,
+                                    text = "Clear",
+                                    contentDescription = "Delete",
+                                    onClick = { state.animateTo(RevealValue.Revealed) },
+                                    shape = CircleShape,
+                                    state = state
+                                )
+                            },
+                            state = state
+                        ) {
+                            Chip(
+                                onClick = { /*TODO*/ },
+                                colors = ChipDefaults.secondaryChipColors(),
+                                modifier = Modifier.fillMaxWidth(),
+                                label = { Text("Try this") }
+                            )
+                        }
+                    }
+                }
+                LaunchedEffect(state.currentValue) {
+                    if (state.currentValue == RevealValue.Revealed) {
+                        delay(2000)
+                        expandableState[curr].expanded = false
                     }
                 }
             }
@@ -298,48 +327,30 @@
 
 @OptIn(ExperimentalWearFoundationApi::class)
 @Composable
-private fun DeleteButton(
-    state: RevealState,
-    coroutineScope: CoroutineScope,
-    shape: Shape = CircleShape,
+private fun RevealScope.SwipeToRevealAction(
+    color: Color,
+    icon: ImageVector,
+    text: String? = null,
+    contentDescription: String? = null,
+    onClick: suspend () -> Unit = {},
+    shape: Shape = RoundedCornerShape(15.dp),
+    state: RevealState = rememberRevealState(),
+    coroutineScope: CoroutineScope = rememberCoroutineScope(),
 ) {
-    Box(
+    Row(
         modifier = Modifier
             .clickable {
-                coroutineScope.launch { state.animateTo(RevealValue.Revealed) }
+                coroutineScope.launch { onClick() }
             }
-            .background(MaterialTheme.colors.error, shape)
+            .background(color, shape)
             .fillMaxSize(),
-        contentAlignment = Alignment.Center
+        horizontalArrangement = Arrangement.Center,
+        verticalAlignment = Alignment.CenterVertically
     ) {
-        Icon(
-            imageVector = Icons.Outlined.Delete,
-            contentDescription = "Delete",
-            tint = Color.Black,
-        )
-    }
-}
-
-@OptIn(ExperimentalWearFoundationApi::class)
-@Composable
-private fun MoreOptionsButton(
-    state: RevealState,
-    coroutineScope: CoroutineScope,
-    shape: Shape = CircleShape,
-) {
-    Box(
-        modifier = Modifier
-            .clickable {
-                coroutineScope.launch { state.animateTo(RevealValue.Covered) }
-            }
-            .background(MaterialTheme.colors.onSurfaceVariant, shape)
-            .fillMaxSize(),
-        contentAlignment = Alignment.Center
-    ) {
-        Icon(
-            imageVector = Icons.Outlined.MoreVert,
-            contentDescription = "More Options",
-            tint = Color.DarkGray,
-        )
+        Icon(imageVector = icon, contentDescription = contentDescription, tint = Color.DarkGray)
+        if (abs(state.offset) > revealOffset && text != null) {
+            Spacer(Modifier.size(5.dp))
+            Text(text = text)
+        }
     }
 }
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/current.txt b/wear/protolayout/protolayout-expression-pipeline/api/current.txt
index a4ee560..712985a 100644
--- a/wear/protolayout/protolayout-expression-pipeline/api/current.txt
+++ b/wear/protolayout/protolayout-expression-pipeline/api/current.txt
@@ -16,12 +16,9 @@
     method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, android.icu.util.ULocale, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.String!>);
   }
 
-  public class DynamicTypeEvaluator implements java.lang.AutoCloseable {
+  public class DynamicTypeEvaluator {
     ctor public DynamicTypeEvaluator(androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config);
     method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest) throws androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.EvaluationException;
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void close();
-    method @UiThread public void disablePlatformDataSources();
-    method @UiThread public void enablePlatformDataSources();
   }
 
   public static final class DynamicTypeEvaluator.Config {
@@ -30,7 +27,6 @@
     method public androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway? getSensorGateway();
     method public androidx.wear.protolayout.expression.pipeline.StateStore? getStateStore();
     method public androidx.wear.protolayout.expression.pipeline.TimeGateway? getTimeGateway();
-    method public boolean isPlatformDataSourcesInitiallyEnabled();
   }
 
   public static final class DynamicTypeEvaluator.Config.Builder {
@@ -38,7 +34,6 @@
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config build();
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setAnimationQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setDynamicTypesQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
-    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setPlatformDataSourcesInitiallyEnabled(boolean);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setSensorGateway(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setStateStore(androidx.wear.protolayout.expression.pipeline.StateStore);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setTimeGateway(androidx.wear.protolayout.expression.pipeline.TimeGateway);
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt
index a4ee560..712985a 100644
--- a/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt
@@ -16,12 +16,9 @@
     method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, android.icu.util.ULocale, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.String!>);
   }
 
-  public class DynamicTypeEvaluator implements java.lang.AutoCloseable {
+  public class DynamicTypeEvaluator {
     ctor public DynamicTypeEvaluator(androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config);
     method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest) throws androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.EvaluationException;
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void close();
-    method @UiThread public void disablePlatformDataSources();
-    method @UiThread public void enablePlatformDataSources();
   }
 
   public static final class DynamicTypeEvaluator.Config {
@@ -30,7 +27,6 @@
     method public androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway? getSensorGateway();
     method public androidx.wear.protolayout.expression.pipeline.StateStore? getStateStore();
     method public androidx.wear.protolayout.expression.pipeline.TimeGateway? getTimeGateway();
-    method public boolean isPlatformDataSourcesInitiallyEnabled();
   }
 
   public static final class DynamicTypeEvaluator.Config.Builder {
@@ -38,7 +34,6 @@
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config build();
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setAnimationQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setDynamicTypesQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
-    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setPlatformDataSourcesInitiallyEnabled(boolean);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setSensorGateway(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setStateStore(androidx.wear.protolayout.expression.pipeline.StateStore);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setTimeGateway(androidx.wear.protolayout.expression.pipeline.TimeGateway);
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt b/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt
index 72f6bf6..f5ae829 100644
--- a/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt
@@ -16,12 +16,9 @@
     method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, android.icu.util.ULocale, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.String!>);
   }
 
-  public class DynamicTypeEvaluator implements java.lang.AutoCloseable {
+  public class DynamicTypeEvaluator {
     ctor public DynamicTypeEvaluator(androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config);
     method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest) throws androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.EvaluationException;
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void close();
-    method @UiThread public void disablePlatformDataSources();
-    method @UiThread public void enablePlatformDataSources();
   }
 
   public static final class DynamicTypeEvaluator.Config {
@@ -30,7 +27,6 @@
     method public androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway? getSensorGateway();
     method public androidx.wear.protolayout.expression.pipeline.StateStore? getStateStore();
     method public androidx.wear.protolayout.expression.pipeline.TimeGateway? getTimeGateway();
-    method public boolean isPlatformDataSourcesInitiallyEnabled();
   }
 
   public static final class DynamicTypeEvaluator.Config.Builder {
@@ -38,7 +34,6 @@
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config build();
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setAnimationQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setDynamicTypesQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
-    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setPlatformDataSourcesInitiallyEnabled(boolean);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setSensorGateway(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setStateStore(androidx.wear.protolayout.expression.pipeline.StateStore);
     method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setTimeGateway(androidx.wear.protolayout.expression.pipeline.TimeGateway);
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java
index 3ece394..068ce4b 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java
@@ -21,13 +21,11 @@
 import android.icu.util.ULocale;
 import android.os.Handler;
 import android.os.Looper;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
-import androidx.annotation.UiThread;
 import androidx.wear.protolayout.expression.DynamicBuilders;
 import androidx.wear.protolayout.expression.pipeline.BoolNodes.ComparisonFloatNode;
 import androidx.wear.protolayout.expression.pipeline.BoolNodes.ComparisonInt32Node;
@@ -102,7 +100,7 @@
  * <p>It's the callers responsibility to destroy those dynamic types after use, with {@link
  * BoundDynamicType#close()}.
  */
-public class DynamicTypeEvaluator implements AutoCloseable {
+public class DynamicTypeEvaluator {
     private static final String TAG = "DynamicTypeEvaluator";
     private static final QuotaManager NO_OP_QUOTA_MANAGER =
             new FixedQuotaManagerImpl(Integer.MAX_VALUE);
@@ -131,17 +129,14 @@
 
     @NonNull private static final StateStore EMPTY_STATE_STORE = new StateStore(emptyMap());
 
-    @NonNull private final Config mConfig;
     @NonNull private final StateStore mStateStore;
     @NonNull private final QuotaManager mAnimationQuotaManager;
     @NonNull private final QuotaManager mDynamicTypesQuotaManager;
-    @NonNull private final TimeGateway mTimeGateway;
-    @Nullable private final EpochTimePlatformDataSource mTimeDataSource;
+    @NonNull private final EpochTimePlatformDataSource mTimeDataSource;
     @Nullable private final SensorGatewayPlatformDataSource mSensorGatewayDataSource;
 
     /** Configuration for creating {@link DynamicTypeEvaluator}. */
     public static final class Config {
-        private final boolean mPlatformDataSourcesInitiallyEnabled;
         @Nullable private final StateStore mStateStore;
         @Nullable private final QuotaManager mAnimationQuotaManager;
         @Nullable private final TimeGateway mTimeGateway;
@@ -149,13 +144,11 @@
         @Nullable private final QuotaManager mDynamicTypesQuotaManager;
 
         Config(
-                boolean platformDataSourcesInitiallyEnabled,
                 @Nullable StateStore stateStore,
                 @Nullable QuotaManager animationQuotaManager,
                 @Nullable QuotaManager dynamicTypesQuotaManager,
                 @Nullable TimeGateway timeGateway,
                 @Nullable SensorGateway sensorGateway) {
-            this.mPlatformDataSourcesInitiallyEnabled = platformDataSourcesInitiallyEnabled;
             this.mStateStore = stateStore;
             this.mAnimationQuotaManager = animationQuotaManager;
             this.mTimeGateway = timeGateway;
@@ -165,7 +158,6 @@
 
         /** Builds a {@link DynamicTypeEvaluator.Config}. */
         public static final class Builder {
-            private boolean mPlatformDataSourcesInitiallyEnabled = false;
             @Nullable private StateStore mStateStore = null;
             @Nullable private QuotaManager mAnimationQuotaManager = null;
             @Nullable private QuotaManager mDynamicTypesQuotaManager;
@@ -174,19 +166,6 @@
             @Nullable private SensorGateway mSensorGateway = null;
 
             /**
-             * Sets whether sending updates from sensor and time sources should be allowed
-             * initially. After that, enabling updates from sensor and time sources can be done via
-             * {@link #enablePlatformDataSources()} or {@link #disablePlatformDataSources()}.
-             *
-             * <p>Defaults to {@code false}.
-             */
-            @NonNull
-            public Builder setPlatformDataSourcesInitiallyEnabled(boolean value) {
-                mPlatformDataSourcesInitiallyEnabled = value;
-                return this;
-            }
-
-            /**
              * Sets the state store that will be used for dereferencing the state keys in the
              * dynamic types.
              *
@@ -251,7 +230,6 @@
             @NonNull
             public Config build() {
                 return new Config(
-                        mPlatformDataSourcesInitiallyEnabled,
                         mStateStore,
                         mAnimationQuotaManager,
                         mDynamicTypesQuotaManager,
@@ -261,15 +239,6 @@
         }
 
         /**
-         * Gets whether sending updates from sensor and time sources should be allowed initially.
-         * After that, enabling updates from sensor and time sources can be done via {@link
-         * #enablePlatformDataSources()} or {@link #disablePlatformDataSources()}.
-         */
-        public boolean isPlatformDataSourcesInitiallyEnabled() {
-            return mPlatformDataSourcesInitiallyEnabled;
-        }
-
-        /**
          * Gets the state store that will be used for dereferencing the state keys in the dynamic
          * types, or {@code null} which is equivalent to an empty state store (state bindings will
          * trigger {@link DynamicTypeValueReceiver#onInvalidated()}).
@@ -320,7 +289,6 @@
 
     /** Constructs a {@link DynamicTypeEvaluator}. */
     public DynamicTypeEvaluator(@NonNull Config config) {
-        this.mConfig = config;
         this.mStateStore =
                 config.getStateStore() != null ? config.getStateStore() : EMPTY_STATE_STORE;
         this.mAnimationQuotaManager =
@@ -333,21 +301,13 @@
                         : NO_OP_QUOTA_MANAGER;
         Handler uiHandler = new Handler(Looper.getMainLooper());
         MainThreadExecutor uiExecutor = new MainThreadExecutor(uiHandler);
-        this.mTimeGateway =
-                config.getTimeGateway() != null
-                        ? config.getTimeGateway()
-                        : new TimeGatewayImpl(uiHandler);
-        this.mTimeDataSource = new EpochTimePlatformDataSource(uiExecutor, mTimeGateway);
-        if (config.isPlatformDataSourcesInitiallyEnabled()
-                && this.mTimeGateway instanceof TimeGatewayImpl) {
-            ((TimeGatewayImpl) this.mTimeGateway).enableUpdates();
+        TimeGateway timeGateway = config.getTimeGateway();
+        if (timeGateway == null) {
+                timeGateway = new TimeGatewayImpl(uiHandler);
+                ((TimeGatewayImpl) timeGateway).enableUpdates();
         }
+        this.mTimeDataSource = new EpochTimePlatformDataSource(uiExecutor, timeGateway);
         if (config.getSensorGateway() != null) {
-            if (config.isPlatformDataSourcesInitiallyEnabled()) {
-                config.getSensorGateway().enableUpdates();
-            } else {
-                config.getSensorGateway().disableUpdates();
-            }
             this.mSensorGatewayDataSource =
                     new SensorGatewayPlatformDataSource(uiExecutor, config.getSensorGateway());
         } else {
@@ -1102,46 +1062,6 @@
         resultBuilder.add(node);
     }
 
-    /** Enables sending updates on sensor and time. */
-    @UiThread
-    public void enablePlatformDataSources() {
-        if (this.mTimeGateway instanceof TimeGatewayImpl) {
-            ((TimeGatewayImpl) mTimeGateway).enableUpdates();
-        }
-        if (mConfig.getSensorGateway() != null) {
-            mConfig.getSensorGateway().enableUpdates();
-        }
-    }
-
-    /** Disables sending updates on sensor and time. */
-    @UiThread
-    public void disablePlatformDataSources() {
-        if (this.mTimeGateway instanceof TimeGatewayImpl) {
-            ((TimeGatewayImpl) mTimeGateway).disableUpdates();
-        }
-        if (mConfig.getSensorGateway() != null) {
-            mConfig.getSensorGateway().disableUpdates();
-        }
-    }
-
-    /**
-     * Closes resources owned by this {@link DynamicTypeEvaluator}.
-     *
-     * <p>This will not close provided resources, like the {@link TimeGateway} or {@link
-     * SensorGateway}.
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Override
-    public void close() {
-        if (mTimeGateway instanceof TimeGatewayImpl) {
-            try {
-                ((TimeGatewayImpl) mTimeGateway).close();
-            } catch (RuntimeException ex) {
-                Log.e(TAG, "Error while cleaning up time gateway", ex);
-            }
-        }
-    }
-
     /**
      * Wraps {@link DynamicTypeValueReceiver} and executes its methods on the given {@link
      * Executor}.
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FixedQuotaManagerImpl.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FixedQuotaManagerImpl.java
index 6a3f1d3..dbe00c9 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FixedQuotaManagerImpl.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FixedQuotaManagerImpl.java
@@ -60,15 +60,13 @@
     }
 
     /** Returns true if all quota has been released. */
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public boolean isAllQuotaReleased() {
         return mQuotaCounter == 0;
     }
 
     /** Returns the remaining quota. */
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public int getRemainingQuota() {
         return mQuotaCap - mQuotaCounter;
     }
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java
index e30b7c5..67b1243 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java
@@ -92,7 +92,6 @@
         StateStore stateStore = new StateStore(new HashMap<>());
         return new DynamicTypeEvaluator(
                 new DynamicTypeEvaluator.Config.Builder()
-                        .setPlatformDataSourcesInitiallyEnabled(true)
                         .setStateStore(stateStore)
                         .setAnimationQuotaManager(animationQuota)
                         .setDynamicTypesQuotaManager(dynamicTypesQuota)
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/ParametrizedDynamicTypeEvaluatorTest.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/ParametrizedDynamicTypeEvaluatorTest.java
index 86a002e..7632f30 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/ParametrizedDynamicTypeEvaluatorTest.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/ParametrizedDynamicTypeEvaluatorTest.java
@@ -326,7 +326,6 @@
         DynamicTypeEvaluator evaluator =
                 new DynamicTypeEvaluator(
                         new DynamicTypeEvaluator.Config.Builder()
-                                .setPlatformDataSourcesInitiallyEnabled(true)
                                 .setStateStore(stateStore)
                                 .setAnimationQuotaManager(new FixedQuotaManagerImpl(MAX_VALUE))
                                 .build());
@@ -491,6 +490,7 @@
         }
 
         @Override
+        @NonNull
         public String toString() {
             return mName + " = " + mExpectedValue;
         }
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java
index ba47d07..be3cff9 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java
@@ -24,6 +24,8 @@
 import android.annotation.SuppressLint;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.icu.util.ULocale;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -46,6 +48,7 @@
 import androidx.wear.protolayout.expression.pipeline.FixedQuotaManagerImpl;
 import androidx.wear.protolayout.expression.pipeline.QuotaManager;
 import androidx.wear.protolayout.expression.pipeline.StateStore;
+import androidx.wear.protolayout.expression.pipeline.TimeGatewayImpl;
 import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway;
 import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicBool;
 import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicColor;
@@ -92,16 +95,15 @@
     boolean mFullyVisible;
     @NonNull final QuotaManager mAnimationQuotaManager;
     @NonNull private final DynamicTypeEvaluator mEvaluator;
+    @NonNull private final TimeGatewayImpl mTimeGateway;
 
     /** Creates a {@link ProtoLayoutDynamicDataPipeline} without animation support. */
     @RestrictTo(Scope.LIBRARY_GROUP)
     public ProtoLayoutDynamicDataPipeline(
-            boolean canUpdateGateways,
             @Nullable SensorGateway sensorGateway,
             @NonNull StateStore stateStore) {
         // Build pipeline with quota that doesn't allow any animations.
         this(
-                canUpdateGateways,
                 sensorGateway,
                 stateStore,
                 /* enableAnimations= */ false,
@@ -115,13 +117,11 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     public ProtoLayoutDynamicDataPipeline(
-            boolean canUpdateGateways,
             @Nullable SensorGateway sensorGateway,
             @NonNull StateStore stateStore,
             @NonNull QuotaManager animationQuotaManager,
             @NonNull QuotaManager dynamicNodesQuotaManager) {
         this(
-                canUpdateGateways,
                 sensorGateway,
                 stateStore,
                 /* enableAnimations= */ true,
@@ -131,7 +131,6 @@
 
     /** Creates a {@link ProtoLayoutDynamicDataPipeline}. */
     private ProtoLayoutDynamicDataPipeline(
-            boolean canUpdateGateways,
             @Nullable SensorGateway sensorGateway,
             @NonNull StateStore stateStore,
             boolean enableAnimations,
@@ -139,9 +138,10 @@
             @NonNull QuotaManager dynamicNodeQuotaManager) {
         this.mEnableAnimations = enableAnimations;
         this.mAnimationQuotaManager = animationQuotaManager;
+        this.mTimeGateway = new TimeGatewayImpl(new Handler(Looper.getMainLooper()));
         DynamicTypeEvaluator.Config.Builder evaluatorConfigBuilder =
                 new DynamicTypeEvaluator.Config.Builder()
-                        .setPlatformDataSourcesInitiallyEnabled(canUpdateGateways)
+                        .setTimeGateway(mTimeGateway)
                         .setStateStore(stateStore);
         evaluatorConfigBuilder.setDynamicTypesQuotaManager(dynamicNodeQuotaManager);
         if (sensorGateway != null) {
@@ -150,12 +150,12 @@
         if (enableAnimations) {
             evaluatorConfigBuilder.setAnimationQuotaManager(animationQuotaManager);
         }
-        this.mEvaluator = new DynamicTypeEvaluator(evaluatorConfigBuilder.build());
+        DynamicTypeEvaluator.Config evaluatorConfig = evaluatorConfigBuilder.build();
+        this.mEvaluator = new DynamicTypeEvaluator(evaluatorConfig);
     }
 
     /** Returns the number of active dynamic types in this pipeline. */
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public int size() {
         return mPositionIdTree.getAllNodes().stream().mapToInt(NodeInfo::size).sum();
     }
@@ -186,7 +186,6 @@
      */
     @VisibleForTesting
     @NonNull
-    @RestrictTo(Scope.TESTS)
     public PipelineMaker newPipelineMaker() {
         return newPipelineMaker(
                 (enterTransition, view) -> new AnimationSet(/* shareInterpolator= */ false),
@@ -201,10 +200,12 @@
     @SuppressWarnings("RestrictTo")
     @RestrictTo(Scope.LIBRARY_GROUP)
     public void setUpdatesEnabled(boolean canUpdate) {
+        // SensorGateway is not owned by ProtoLayoutDynamicDataPipeline, so the callers who create
+        // it are responsible for updates.
         if (canUpdate) {
-            mEvaluator.enablePlatformDataSources();
+            mTimeGateway.enableUpdates();
         } else {
-            mEvaluator.disablePlatformDataSources();
+            mTimeGateway.disableUpdates();
         }
     }
 
@@ -212,7 +213,8 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     @SuppressWarnings("RestrictTo")
     public void close() {
-        mEvaluator.close();
+        mPositionIdTree.clear();
+        mTimeGateway.close();
     }
 
     /**
@@ -1062,8 +1064,7 @@
     }
 
     /** Returns how many animations are running. */
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public int getRunningAnimationsCount() {
         return mPositionIdTree.getAllNodes().stream()
                         .mapToInt(NodeInfo::getRunningAnimationCount)
@@ -1077,8 +1078,7 @@
     }
 
     /** Returns How many dynamic data nodes exist in the pipeline. */
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public int getDynamicExpressionsNodesCount() {
         return mPositionIdTree.getAllNodes().stream()
                 .mapToInt(NodeInfo::getExpressionNodesCount)
@@ -1086,8 +1086,7 @@
     }
 
     /** Returns whether all quota has been released. */
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    @RestrictTo(Scope.TESTS)
+    @VisibleForTesting
     public boolean isAllQuotaReleased() {
         return mAnimationQuotaManager instanceof FixedQuotaManagerImpl
                 && ((FixedQuotaManagerImpl) mAnimationQuotaManager).isAllQuotaReleased();
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java
index 19fafca..b496675 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java
@@ -646,17 +646,15 @@
 
         StateStore stateStore = config.getStateStore();
         if (stateStore != null) {
-            boolean updatesEnabled = config.getUpdatesEnabled();
             mDataPipeline =
                     config.getAnimationEnabled()
                             ? new ProtoLayoutDynamicDataPipeline(
-                                    updatesEnabled,
-                                    config.getSensorGateway(),
+                            config.getSensorGateway(),
                                     stateStore,
                                     new FixedQuotaManagerImpl(config.getRunningAnimationsLimit()),
                                     new FixedQuotaManagerImpl(DYNAMIC_NODES_MAX_COUNT))
                             : new ProtoLayoutDynamicDataPipeline(
-                                    updatesEnabled, config.getSensorGateway(), stateStore);
+                                    config.getSensorGateway(), stateStore);
             mDataPipeline.setFullyVisible(config.getIsViewFullyVisible());
         } else {
             mDataPipeline = null;
diff --git a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java
index c93a489..f8c0a3d 100644
--- a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java
+++ b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java
@@ -377,7 +377,6 @@
                         .build();
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -444,7 +443,6 @@
         DynamicInt32 dynamicInt = fixedDynamicInt32(1);
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -465,7 +463,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -496,7 +493,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -525,7 +521,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -582,7 +577,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -621,7 +615,6 @@
         List<String> expected = Arrays.asList(NODE_1_1, NODE_1_1_1);
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -643,7 +636,6 @@
     public void resolvedAnimatedImage_canStorePlayAndResetOnVisible() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -677,7 +669,6 @@
     public void resolvedAnimatedImage_canStoreAndPlayOnVisibleOnce() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -709,7 +700,6 @@
     public void resolvedAnimatedImage_canStorePlayAndResetOnLoad() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -738,7 +728,6 @@
         String boolStateKey = "KEY";
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -776,7 +765,6 @@
         String boolStateKey = "KEY";
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -797,7 +785,6 @@
         String boolStateKey = "KEY";
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -820,7 +807,6 @@
         FixedQuotaManagerImpl quotaManager = new FixedQuotaManagerImpl(MAX_VALUE);
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -854,7 +840,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -892,7 +877,6 @@
         FixedQuotaManagerImpl quotaManager = new FixedQuotaManagerImpl(/* quotaCap= */ 0);
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -920,7 +904,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -958,7 +941,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1008,7 +990,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1040,7 +1021,6 @@
         FixedQuotaManagerImpl quotaManager = new FixedQuotaManagerImpl(/* quotaCap= */ 0);
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -1125,7 +1105,6 @@
     public void resolvedSeekableAnimatedImage_canStoreAndRegisterWithAnimatableFixedFloat() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1158,7 +1137,6 @@
     public void resolvedSeekableAnimatedImage_canStoreAndRegisterWithAnimatableDynamicFloat() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1204,7 +1182,6 @@
     public void resolvedSeekableAnimatedImage_getSeekableAnimationTotalDurationMillis() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1228,7 +1205,6 @@
     public void whenInvisible_pausesAvds() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1264,7 +1240,6 @@
     public void visibilityChange_avdsStatusChange() {
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         new FixedQuotaManagerImpl(MAX_VALUE),
@@ -1377,7 +1352,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -1431,7 +1405,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -1488,7 +1461,6 @@
 
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -1546,7 +1518,6 @@
         FixedQuotaManagerImpl quotaManager = new FixedQuotaManagerImpl(1);
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -1798,7 +1769,6 @@
                 Trigger.newBuilder().setOnLoadTrigger(OnLoadTrigger.getDefaultInstance()).build();
         ProtoLayoutDynamicDataPipeline pipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
                         /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
@@ -1843,13 +1813,11 @@
         ProtoLayoutDynamicDataPipeline pipeline =
                 enableAnimations
                         ? new ProtoLayoutDynamicDataPipeline(
-                                /* canUpdateGateways= */ true,
-                                /* sensorGateway= */ null,
+                        /* sensorGateway= */ null,
                                 mStateStore,
                                 new FixedQuotaManagerImpl(MAX_VALUE),
                                 new FixedQuotaManagerImpl(MAX_VALUE))
                         : new ProtoLayoutDynamicDataPipeline(
-                                /* canUpdateGateways= */ true,
                                 /* sensorGateway= */ null,
                                 mStateStore);
         shadowOf(getMainLooper()).idle();
@@ -1874,8 +1842,7 @@
         AddToListCallback<Float> receiver =
                 new AddToListCallback<>(results, /* invalidList= */ null);
         ProtoLayoutDynamicDataPipeline pipeline =
-                new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true, /* sensorGateway= */ null, mStateStore);
+                new ProtoLayoutDynamicDataPipeline(  /* sensorGateway= */ null, mStateStore);
         shadowOf(getMainLooper()).idle();
 
         pipeline.setFullyVisible(true);
@@ -1893,8 +1860,7 @@
         AddToListCallback<Integer> receiver =
                 new AddToListCallback<>(results, /* invalidList= */ null);
         ProtoLayoutDynamicDataPipeline pipeline =
-                new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true, /* sensorGateway= */ null, mStateStore);
+                new ProtoLayoutDynamicDataPipeline(  /* sensorGateway= */ null, mStateStore);
         shadowOf(getMainLooper()).idle();
 
         pipeline.setFullyVisible(true);
@@ -1912,8 +1878,7 @@
         AddToListCallback<Float> receiver =
                 new AddToListCallback<>(results, /* invalidList= */ null);
         ProtoLayoutDynamicDataPipeline pipeline =
-                new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true, /* sensorGateway= */ null, mStateStore);
+                new ProtoLayoutDynamicDataPipeline(  /* sensorGateway= */ null, mStateStore);
         shadowOf(getMainLooper()).idle();
 
         pipeline.setFullyVisible(true);
@@ -1931,8 +1896,7 @@
         AddToListCallback<Float> receiver =
                 new AddToListCallback<>(results, /* invalidList= */ null);
         ProtoLayoutDynamicDataPipeline pipeline =
-                new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true, /* sensorGateway= */ null, mStateStore);
+                new ProtoLayoutDynamicDataPipeline(  /* sensorGateway= */ null, mStateStore);
         shadowOf(getMainLooper()).idle();
 
         pipeline.setFullyVisible(true);
@@ -1950,8 +1914,7 @@
         AddToListCallback<Integer> receiver =
                 new AddToListCallback<>(results, /* invalidList= */ null);
         ProtoLayoutDynamicDataPipeline pipeline =
-                new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true, /* sensorGateway= */ null, mStateStore);
+                new ProtoLayoutDynamicDataPipeline(  /* sensorGateway= */ null, mStateStore);
         shadowOf(getMainLooper()).idle();
 
         pipeline.setFullyVisible(true);
diff --git a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
index 4a49fcd..9e263bf 100644
--- a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
+++ b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
@@ -3378,8 +3378,7 @@
             FixedQuotaManagerImpl quotaManager) {
         mDataPipeline =
                 new ProtoLayoutDynamicDataPipeline(
-                        /* canUpdateGateways= */ true,
-                        null,
+                        /* sensorGateway= */ null,
                         mStateStore,
                         quotaManager,
                         new FixedQuotaManagerImpl(MAX_VALUE));
diff --git a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
index 26dc1e9..daae481 100644
--- a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
+++ b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
@@ -35,7 +35,6 @@
 import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
 import androidx.wear.watchface.complications.data.ComplicationData
-import androidx.wear.watchface.complications.data.ComplicationDataExpressionEvaluator.Companion.hasExpression
 import androidx.wear.watchface.complications.data.ComplicationType
 import androidx.wear.watchface.complications.data.ComplicationType.Companion.fromWireType
 import androidx.wear.watchface.complications.data.GoalProgressComplicationData
@@ -616,7 +615,7 @@
                 require(complicationData.validTimeRange == TimeRange.ALWAYS) {
                     "Preview data should have time range set to ALWAYS."
                 }
-                require(!hasExpression(complicationData.asWireComplicationData())) {
+                require(!complicationData.asWireComplicationData().hasExpression()) {
                     "Preview data must not have expressions."
                 }
             }
diff --git a/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataTimelineTest.java b/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataTimelineTest.java
index 5463ef96..5423cf2 100644
--- a/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataTimelineTest.java
+++ b/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataTimelineTest.java
@@ -150,7 +150,8 @@
                                 + "validTimeRange=TimeRange("
                                 + "startDateTimeMillis=-1000000000-01-01T00:00:00Z,"
                                 + " endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z),"
-                                + " dataSource=null, persistencePolicy=0, displayPolicy=0),"
+                                + " dataSource=null, persistencePolicy=0, displayPolicy=0, "
+                                + "fallback=null),"
                                 + " timelineEntries=["
                                 + "TimelineEntry(validity=TimeInterval(start=1970-01-02T03:46:40Z,"
                                 + " end=1970-01-03T07:33:20Z),"
@@ -164,7 +165,8 @@
                                 + "validTimeRange=TimeRange("
                                 + "startDateTimeMillis=-1000000000-01-01T00:00:00Z,"
                                 + " endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z),"
-                                + " dataSource=null, persistencePolicy=0, displayPolicy=0))])");
+                                + " dataSource=null, persistencePolicy=0, displayPolicy=0, "
+                                + "fallback=null))])");
     }
 
     @Test
diff --git a/wear/watchface/watchface-complications-data/api/current.ignore b/wear/watchface/watchface-complications-data/api/current.ignore
index 123515f..aa5a43b 100644
--- a/wear/watchface/watchface-complications-data/api/current.ignore
+++ b/wear/watchface/watchface-complications-data/api/current.ignore
@@ -1,4 +1,20 @@
 // Baseline format: 1.0
+ChangedType: androidx.wear.watchface.complications.data.LongTextComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.LongTextComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.LongTextComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder to BuilderT
+
+
 RemovedClass: androidx.wear.watchface.complications.data.DataKt:
     Removed class androidx.wear.watchface.complications.data.DataKt
 RemovedClass: androidx.wear.watchface.complications.data.ImageKt:
diff --git a/wear/watchface/watchface-complications-data/api/current.txt b/wear/watchface/watchface-complications-data/api/current.txt
index f36afa5..2992e08 100644
--- a/wear/watchface/watchface-complications-data/api/current.txt
+++ b/wear/watchface/watchface-complications-data/api/current.txt
@@ -113,10 +113,10 @@
     ctor public GoalProgressComplicationData.Builder(float value, float targetValue, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData build();
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setColorRamp(androidx.wear.watchface.complications.data.ColorRamp? colorRamp);
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
@@ -141,10 +141,10 @@
   public static final class LongTextComplicationData.Builder {
     ctor public LongTextComplicationData.Builder(androidx.wear.watchface.complications.data.ComplicationText text, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? icon);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -176,9 +176,9 @@
   public static final class MonochromaticImageComplicationData.Builder {
     ctor public MonochromaticImageComplicationData.Builder(androidx.wear.watchface.complications.data.MonochromaticImage monochromaticImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -208,10 +208,10 @@
   public static final class NoPermissionComplicationData.Builder {
     ctor public NoPermissionComplicationData.Builder();
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -234,9 +234,9 @@
   public static final class PhotoImageComplicationData.Builder {
     ctor public PhotoImageComplicationData.Builder(android.graphics.drawable.Icon photoImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -285,10 +285,10 @@
     ctor public RangedValueComplicationData.Builder(float value, float min, float max, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData build();
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setColorRamp(androidx.wear.watchface.complications.data.ColorRamp? colorRamp);
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
@@ -315,10 +315,10 @@
   public static final class ShortTextComplicationData.Builder {
     ctor public ShortTextComplicationData.Builder(androidx.wear.watchface.complications.data.ComplicationText text, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -352,9 +352,9 @@
   public static final class SmallImageComplicationData.Builder {
     ctor public SmallImageComplicationData.Builder(androidx.wear.watchface.complications.data.SmallImage smallImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -459,11 +459,11 @@
   @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class WeightedElementsComplicationData.Builder {
     ctor public WeightedElementsComplicationData.Builder(java.util.List<androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Element> elements, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setElementBackgroundColor(@ColorInt int elementBackgroundColor);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
diff --git a/wear/watchface/watchface-complications-data/api/public_plus_experimental_current.txt b/wear/watchface/watchface-complications-data/api/public_plus_experimental_current.txt
index 520f8dc..e6efd13 100644
--- a/wear/watchface/watchface-complications-data/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-complications-data/api/public_plus_experimental_current.txt
@@ -116,10 +116,10 @@
     ctor public GoalProgressComplicationData.Builder(float value, float targetValue, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData build();
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setColorRamp(androidx.wear.watchface.complications.data.ColorRamp? colorRamp);
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
@@ -144,10 +144,10 @@
   public static final class LongTextComplicationData.Builder {
     ctor public LongTextComplicationData.Builder(androidx.wear.watchface.complications.data.ComplicationText text, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? icon);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -179,9 +179,9 @@
   public static final class MonochromaticImageComplicationData.Builder {
     ctor public MonochromaticImageComplicationData.Builder(androidx.wear.watchface.complications.data.MonochromaticImage monochromaticImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -211,10 +211,10 @@
   public static final class NoPermissionComplicationData.Builder {
     ctor public NoPermissionComplicationData.Builder();
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -237,9 +237,9 @@
   public static final class PhotoImageComplicationData.Builder {
     ctor public PhotoImageComplicationData.Builder(android.graphics.drawable.Icon photoImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -288,10 +288,10 @@
     ctor public RangedValueComplicationData.Builder(float value, float min, float max, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData build();
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setColorRamp(androidx.wear.watchface.complications.data.ColorRamp? colorRamp);
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
@@ -318,10 +318,10 @@
   public static final class ShortTextComplicationData.Builder {
     ctor public ShortTextComplicationData.Builder(androidx.wear.watchface.complications.data.ComplicationText text, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -355,9 +355,9 @@
   public static final class SmallImageComplicationData.Builder {
     ctor public SmallImageComplicationData.Builder(androidx.wear.watchface.complications.data.SmallImage smallImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -462,11 +462,11 @@
   @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class WeightedElementsComplicationData.Builder {
     ctor public WeightedElementsComplicationData.Builder(java.util.List<androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Element> elements, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setElementBackgroundColor(@ColorInt int elementBackgroundColor);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
diff --git a/wear/watchface/watchface-complications-data/api/restricted_current.ignore b/wear/watchface/watchface-complications-data/api/restricted_current.ignore
index d3ed8b1..fa0dab0 100644
--- a/wear/watchface/watchface-complications-data/api/restricted_current.ignore
+++ b/wear/watchface/watchface-complications-data/api/restricted_current.ignore
@@ -1,4 +1,20 @@
 // Baseline format: 1.0
+ChangedType: androidx.wear.watchface.complications.data.LongTextComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.LongTextComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.LongTextComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder to BuilderT
+ChangedType: androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder#setDataSource(android.content.ComponentName):
+    Method androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder.setDataSource has changed return type from androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder to BuilderT
+
+
 RemovedClass: androidx.wear.watchface.complications.data.DataKt:
     Removed class androidx.wear.watchface.complications.data.DataKt
 RemovedClass: androidx.wear.watchface.complications.data.DefaultComplicationDataSourcePolicyWireFormat:
diff --git a/wear/watchface/watchface-complications-data/api/restricted_current.txt b/wear/watchface/watchface-complications-data/api/restricted_current.txt
index a60802c..7a434b5 100644
--- a/wear/watchface/watchface-complications-data/api/restricted_current.txt
+++ b/wear/watchface/watchface-complications-data/api/restricted_current.txt
@@ -113,10 +113,10 @@
     ctor public GoalProgressComplicationData.Builder(float value, float targetValue, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData build();
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setColorRamp(androidx.wear.watchface.complications.data.ColorRamp? colorRamp);
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.GoalProgressComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
@@ -141,10 +141,10 @@
   public static final class LongTextComplicationData.Builder {
     ctor public LongTextComplicationData.Builder(androidx.wear.watchface.complications.data.ComplicationText text, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? icon);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.LongTextComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -176,9 +176,9 @@
   public static final class MonochromaticImageComplicationData.Builder {
     ctor public MonochromaticImageComplicationData.Builder(androidx.wear.watchface.complications.data.MonochromaticImage monochromaticImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.MonochromaticImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -208,10 +208,10 @@
   public static final class NoPermissionComplicationData.Builder {
     ctor public NoPermissionComplicationData.Builder();
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
     method public androidx.wear.watchface.complications.data.NoPermissionComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -234,9 +234,9 @@
   public static final class PhotoImageComplicationData.Builder {
     ctor public PhotoImageComplicationData.Builder(android.graphics.drawable.Icon photoImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.PhotoImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -286,10 +286,10 @@
     ctor public RangedValueComplicationData.Builder(float value, float min, float max, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData build();
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setColorRamp(androidx.wear.watchface.complications.data.ColorRamp? colorRamp);
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.RangedValueComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
@@ -316,10 +316,10 @@
   public static final class ShortTextComplicationData.Builder {
     ctor public ShortTextComplicationData.Builder(androidx.wear.watchface.complications.data.ComplicationText text, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.ShortTextComplicationData.Builder setTitle(androidx.wear.watchface.complications.data.ComplicationText? title);
@@ -353,9 +353,9 @@
   public static final class SmallImageComplicationData.Builder {
     ctor public SmallImageComplicationData.Builder(androidx.wear.watchface.complications.data.SmallImage smallImage, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.SmallImageComplicationData.Builder setValidTimeRange(androidx.wear.watchface.complications.data.TimeRange? validTimeRange);
   }
@@ -462,11 +462,11 @@
   @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class WeightedElementsComplicationData.Builder {
     ctor public WeightedElementsComplicationData.Builder(java.util.List<androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Element> elements, androidx.wear.watchface.complications.data.ComplicationText contentDescription);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData build();
-    method public final T setDataSource(android.content.ComponentName? dataSource);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setDisplayPolicy(int displayPolicy);
+    method public final BuilderT setDataSource(android.content.ComponentName? dataSource);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setDisplayPolicy(int displayPolicy);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setElementBackgroundColor(@ColorInt int elementBackgroundColor);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setMonochromaticImage(androidx.wear.watchface.complications.data.MonochromaticImage? monochromaticImage);
-    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final T setPersistencePolicy(int persistencePolicy);
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final BuilderT setPersistencePolicy(int persistencePolicy);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setSmallImage(androidx.wear.watchface.complications.data.SmallImage? smallImage);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setTapAction(android.app.PendingIntent? tapAction);
     method public androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Builder setText(androidx.wear.watchface.complications.data.ComplicationText? text);
diff --git a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt
index b122f85..4bdd46d 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt
@@ -1115,6 +1115,15 @@
     val endDateTimeMillis: Long
         get() = fields.getLong(FIELD_END_TIME, Long.MAX_VALUE)
 
+    /** Returns `true` if the complication contains an expression that needs to be evaluated. */
+    fun hasExpression(): Boolean =
+        (hasRangedValueExpression() && rangedValueExpression != null) ||
+            (hasLongText() && longText?.expression != null) ||
+            (hasLongTitle() && longTitle?.expression != null) ||
+            (hasShortText() && shortText?.expression != null) ||
+            (hasShortTitle() && shortTitle?.expression != null) ||
+            (hasContentDescription() && contentDescription?.expression != null)
+
     /**
      * Returns true if the complication data contains at least one text field with a value that may
      * change based on the current time.
@@ -2230,6 +2239,9 @@
                 FIELD_END_TIME,
                 FIELD_TIMELINE_ENTRIES,
                 FIELD_TIMELINE_ENTRY_TYPE,
+                // Placeholder or fallback.
+                FIELD_PLACEHOLDER_FIELDS,
+                FIELD_PLACEHOLDER_TYPE,
             )
 
         // Used for validation. OPTIONAL_FIELDS[i] is a list containing all the fields which are
@@ -2313,8 +2325,6 @@
                         FIELD_LONG_TEXT,
                         FIELD_MAX_VALUE,
                         FIELD_MIN_VALUE,
-                        FIELD_PLACEHOLDER_FIELDS,
-                        FIELD_PLACEHOLDER_TYPE,
                         FIELD_SMALL_IMAGE,
                         FIELD_SMALL_IMAGE_BURN_IN_PROTECTION,
                         FIELD_SHORT_TITLE,
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt
index d6589c5..89fbc08 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt
@@ -216,7 +216,6 @@
             evaluator =
                 DynamicTypeEvaluator(
                     DynamicTypeEvaluator.Config.Builder()
-                        .setPlatformDataSourcesInitiallyEnabled(true)
                         .apply { stateStore?.let { setStateStore(it) } }
                         .apply { timeGateway?.let { setTimeGateway(it) } }
                         .apply { sensorGateway?.let { setSensorGateway(it) } }
@@ -243,7 +242,6 @@
                 for (receiver in pendingReceivers + invalidReceivers + completeReceivers) {
                     receiver.close()
                 }
-                if (this@State::evaluator.isInitialized) evaluator.close()
             }
         }
 
@@ -304,16 +302,6 @@
 
     companion object {
         val INVALID_DATA: WireComplicationData = NoDataComplicationData().asWireComplicationData()
-
-        fun hasExpression(data: WireComplicationData): Boolean =
-            data.run {
-                (hasRangedValueExpression() && rangedValueExpression != null) ||
-                    (hasLongText() && longText?.expression != null) ||
-                    (hasLongTitle() && longTitle?.expression != null) ||
-                    (hasShortText() && shortText?.expression != null) ||
-                    (hasShortTitle() && shortTitle?.expression != null) ||
-                    (hasContentDescription() && contentDescription?.expression != null)
-            }
     }
 }
 
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
index 42fe7ce..e34d53c 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ComplicationExperimental::class)
-
 package androidx.wear.watchface.complications.data
 
 import android.app.PendingIntent
@@ -115,7 +113,8 @@
     public val validTimeRange: TimeRange = TimeRange.ALWAYS,
     public val dataSource: ComponentName?,
     @ComplicationPersistencePolicy public val persistencePolicy: Int,
-    @ComplicationDisplayPolicy public val displayPolicy: Int
+    @ComplicationDisplayPolicy public val displayPolicy: Int,
+    private val fallback: ComplicationData?,
 ) {
     /**
      * [tapAction] which is a [PendingIntent] unfortunately can't be serialized. This property is
@@ -132,7 +131,6 @@
      * Converts this value to [WireComplicationData] object used for serialization.
      *
      * This is only needed internally to convert to the underlying communication protocol.
-     *
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public fun asWireComplicationData(): WireComplicationData {
@@ -153,6 +151,13 @@
         builder.setDataSource(dataSource)
         builder.setPersistencePolicy(persistencePolicy)
         builder.setDisplayPolicy(displayPolicy)
+        if (fallback == null) {
+            builder.setPlaceholder(null)
+        } else {
+            val placeholderBuilder = fallback.createWireComplicationDataBuilder()
+            fallback.fillWireComplicationDataBuilder(placeholderBuilder)
+            builder.setPlaceholder(placeholderBuilder.build())
+        }
     }
 
     /**
@@ -186,24 +191,14 @@
 
     override fun hashCode(): Int = asWireComplicationData().hashCode()
 
-    /**
-     * Builder for properties in common for most Complication Types.
-     *
-     */
+    /** Builder for properties in common for most Complication Types. */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
-    public abstract class BaseBuilder<T : BaseBuilder<T, ReturnT>, ReturnT> {
+    public sealed class BaseBuilder<BuilderT : BaseBuilder<BuilderT, BuiltT>, BuiltT> {
         internal var cachedWireComplicationData: WireComplicationData? = null
         internal var dataSource: ComponentName? = null
         internal var persistencePolicy = ComplicationPersistencePolicies.CACHING_ALLOWED
         internal var displayPolicy = ComplicationDisplayPolicies.ALWAYS_DISPLAY
-
-        @Suppress("NewApi")
-        internal fun setCommon(data: WireComplicationData) = apply {
-            setCachedWireComplicationData(data)
-            setDataSource(data.dataSource)
-            setPersistencePolicy(data.persistencePolicy)
-            setDisplayPolicy(data.displayPolicy)
-        }
+        internal var fallback: BuiltT? = null
 
         /**
          * Sets the [ComponentName] of the ComplicationDataSourceService that provided this
@@ -213,37 +208,48 @@
          * set this value on its behalf.
          */
         @Suppress("UNCHECKED_CAST", "SetterReturnsThis")
-        public fun setDataSource(dataSource: ComponentName?): T {
+        public fun setDataSource(dataSource: ComponentName?): BuilderT {
             this.dataSource = dataSource
-            return this as T
+            return this as BuilderT
         }
 
         @Suppress("UNCHECKED_CAST", "SetterReturnsThis")
         internal fun setCachedWireComplicationData(
             cachedWireComplicationData: WireComplicationData?
-        ): T {
+        ): BuilderT {
             this.cachedWireComplicationData = cachedWireComplicationData
-            return this as T
+            return this as BuilderT
         }
 
         /** Sets the complication's [ComplicationPersistencePolicy]. */
         @Suppress("UNCHECKED_CAST", "SetterReturnsThis")
         @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        public fun setPersistencePolicy(@ComplicationPersistencePolicy persistencePolicy: Int): T {
+        public fun setPersistencePolicy(
+            @ComplicationPersistencePolicy persistencePolicy: Int
+        ): BuilderT {
             this.persistencePolicy = persistencePolicy
-            return this as T
+            return this as BuilderT
         }
 
         /** Sets the complication's [ComplicationDisplayPolicy]. */
         @Suppress("UNCHECKED_CAST", "SetterReturnsThis")
         @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        public fun setDisplayPolicy(@ComplicationDisplayPolicy displayPolicy: Int): T {
+        public fun setDisplayPolicy(@ComplicationDisplayPolicy displayPolicy: Int): BuilderT {
             this.displayPolicy = displayPolicy
-            return this as T
+            return this as BuilderT
+        }
+
+        /** Sets the complication's fallback, use in case any expression has been invalidated. */
+        // TODO(b/269414040): Unhide complication expression APIs.
+        @Suppress("UNCHECKED_CAST", "SetterReturnsThis")
+        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        public fun setFallback(fallback: BuiltT?): BuilderT {
+            this.fallback = fallback
+            return this as BuilderT
         }
 
         /** Builds the ComplicationData */
-        abstract fun build(): ReturnT
+        abstract fun build(): BuiltT
     }
 }
 
@@ -277,7 +283,8 @@
         dataSource = null,
         persistencePolicy = placeholder?.persistencePolicy
                 ?: ComplicationPersistencePolicies.CACHING_ALLOWED,
-        displayPolicy = placeholder?.displayPolicy ?: ComplicationDisplayPolicies.ALWAYS_DISPLAY
+        displayPolicy = placeholder?.displayPolicy ?: ComplicationDisplayPolicies.ALWAYS_DISPLAY,
+        fallback = placeholder,
     ) {
 
     /** Constructs a NoDataComplicationData without a [placeholder]. */
@@ -303,17 +310,6 @@
             else -> null
         }
 
-    override fun fillWireComplicationDataBuilder(builder: WireComplicationDataBuilder) {
-        super.fillWireComplicationDataBuilder(builder)
-        if (placeholder == null) {
-            builder.setPlaceholder(null)
-        } else {
-            val placeholderBuilder = placeholder.createWireComplicationDataBuilder()
-            placeholder.fillWireComplicationDataBuilder(placeholderBuilder)
-            builder.setPlaceholder(placeholderBuilder.build())
-        }
-    }
-
     override fun toString(): String {
         return "NoDataComplicationData(" +
             "placeholder=$placeholder, " +
@@ -341,7 +337,8 @@
         cachedWireComplicationData = null,
         dataSource = null,
         persistencePolicy = ComplicationPersistencePolicies.CACHING_ALLOWED,
-        displayPolicy = ComplicationDisplayPolicies.ALWAYS_DISPLAY
+        displayPolicy = ComplicationDisplayPolicies.ALWAYS_DISPLAY,
+        fallback = null,
     ) {
     // Always empty.
     override fun fillWireComplicationDataBuilder(builder: WireComplicationDataBuilder) {}
@@ -370,7 +367,8 @@
         cachedWireComplicationData = null,
         dataSource = null,
         persistencePolicy = ComplicationPersistencePolicies.CACHING_ALLOWED,
-        displayPolicy = ComplicationDisplayPolicies.ALWAYS_DISPLAY
+        displayPolicy = ComplicationDisplayPolicies.ALWAYS_DISPLAY,
+        fallback = null,
     ) {
     // Always empty.
     override fun fillWireComplicationDataBuilder(builder: WireComplicationDataBuilder) {}
@@ -400,9 +398,8 @@
  * recommended to choose the [smallImage]. It's best practice for a ComplicationDataSource to
  * specify both a [monochromaticImage] and a [smallImage]
  *
- * A data source that wants to serve a ShortTextComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a ShortTextComplicationData must include the following meta
+ * data in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="SHORT_TEXT"/>
@@ -434,6 +431,7 @@
  *   be rendered as a light grey box.
  * @property contentDescription The content description field for accessibility. Please do not
  *   include the word 'complication' in the description.
+ * @property fallback Used in case any expression has been invalidated.
  */
 public class ShortTextComplicationData
 internal constructor(
@@ -447,7 +445,9 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public val fallback: ShortTextComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -456,7 +456,8 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * Builder for [ShortTextComplicationData].
@@ -465,9 +466,9 @@
      *
      * @param text The main localized [ComplicationText]. This must be less than 7 characters long
      * @param contentDescription Defines localized text that briefly describes content of the
-     * complication. This property is used primarily for accessibility. Since some complications do
-     * not have textual representation this attribute can be used for providing such. Please do not
-     * include the word 'complication' in the description.
+     *   complication. This property is used primarily for accessibility. Since some complications
+     *   do not have textual representation this attribute can be used for providing such. Please do
+     *   not include the word 'complication' in the description.
      */
     public class Builder(
         private val text: ComplicationText,
@@ -516,7 +517,8 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
     }
 
@@ -543,7 +545,8 @@
             "contentDescription=$contentDescription, " +
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
-            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy)"
+            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy, " +
+            "fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() =
@@ -590,9 +593,8 @@
  * recommended to choose the [smallImage]. It's best practice for a ComplicationDataSource to
  * specify both a [monochromaticImage] and a [smallImage].
  *
- * A data source that wants to serve a LongTextComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a LongTextComplicationData must include the following meta data
+ * in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="LONG_TEXT"/>
@@ -614,6 +616,7 @@
  *   be rendered as a light grey box.
  * @property contentDescription The content description field for accessibility. Please do not
  *   include the word 'complication' in the description.
+ * @property fallback Used in case any expression has been invalidated.
  */
 public class LongTextComplicationData
 internal constructor(
@@ -627,7 +630,9 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public val fallback: LongTextComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -636,7 +641,8 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * Builder for [LongTextComplicationData].
@@ -646,9 +652,9 @@
      * @param text Localized main [ComplicationText] to display within the complication. There isn't
      *   an explicit character limit but text may be truncated if too long
      * @param contentDescription Defines localized text that briefly describes content of the
-     * complication. This property is used primarily for accessibility. Since some complications do
-     * not have textual representation this attribute can be used for providing such. Please do not
-     * include the word 'complication' in the description.
+     *   complication. This property is used primarily for accessibility. Since some complications
+     *   do not have textual representation this attribute can be used for providing such. Please do
+     *   not include the word 'complication' in the description.
      */
     public class Builder(
         private val text: ComplicationText,
@@ -697,7 +703,8 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
     }
 
@@ -724,7 +731,8 @@
             "contentDescription=$contentDescription), " +
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
-            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy)"
+            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy, " +
+            "fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() =
@@ -820,9 +828,8 @@
  * recommended to choose the [smallImage]. It's best practice for a ComplicationDataSource to
  * specify both a [monochromaticImage] and a [smallImage].
  *
- * A data source that wants to serve a RangedValueComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a RangedValueComplicationData must include the following meta
+ * data in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="GOAL_PROGRESS"/>
@@ -865,6 +872,7 @@
  * @property valueType The semantic meaning of [value]. The complication renderer may choose to
  *   visually differentiate between the different types, for example rendering a dot on a line/arc
  *   to indicate the value for a [TYPE_RATING].
+ * @property fallback Used in case any expression has been invalidated.
  */
 public class RangedValueComplicationData
 internal constructor(
@@ -884,7 +892,10 @@
     public val colorRamp: ColorRamp?,
     @RangedValueType public val valueType: Int,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public val fallback: RangedValueComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -893,15 +904,15 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * The [DynamicFloat] optionally set by the data source. If present the system will dynamically
      * evaluate this and store the result in [value]. Watch faces can typically ignore this field.
-     *
-     * @hide
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public val valueExpression: DynamicFloat? = valueExpression
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -933,9 +944,9 @@
          * @param max The maximum value. This must be less than [Float.MAX_VALUE]. For
          *   [TYPE_PERCENTAGE] this must be 0f.
          * @param contentDescription Defines localized text that briefly describes content of the
-         * complication. This property is used primarily for accessibility. Since some complications
-         * do not have textual representation this attribute can be used for providing such. Please
-         * do not include the word 'complication' in the description.
+         *   complication. This property is used primarily for accessibility. Since some
+         *   complications do not have textual representation this attribute can be used for
+         *   providing such. Please do not include the word 'complication' in the description.
          */
         public constructor(
             value: Float,
@@ -954,10 +965,11 @@
          * @param max The maximum value. This must be less than [Float.MAX_VALUE]. For
          *   [TYPE_PERCENTAGE] this must be 0f.
          * @param contentDescription Defines localized text that briefly describes content of the
-         * complication. This property is used primarily for accessibility. Since some complications
-         * do not have textual representation this attribute can be used for providing such. Please
-         * do not include the word 'complication' in the description.
+         *   complication. This property is used primarily for accessibility. Since some
+         *   complications do not have textual representation this attribute can be used for
+         *   providing such. Please do not include the word 'complication' in the description.
          */
+        // TODO(b/269414040): Unhide complication expression APIs.
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         public constructor(
             valueExpression: DynamicFloat,
@@ -1058,7 +1070,8 @@
                 colorRamp,
                 valueType,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
         }
     }
@@ -1109,7 +1122,7 @@
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
             "colorRamp=$colorRamp, persistencePolicy=$persistencePolicy, " +
-            "displayPolicy=$displayPolicy)"
+            "displayPolicy=$displayPolicy, fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() =
@@ -1186,9 +1199,8 @@
  * [RangedValueComplicationData.TYPE_RATING] into
  * [RangedValueComplicationData.Builder.setValueType].
  *
- * A data source that wants to serve a SmallImageComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a SmallImageComplicationData must include the following meta
+ * data in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *        android:value="GOAL_PROGRESS"/>
@@ -1227,6 +1239,7 @@
  *   include the word 'complication' in the description.
  * @property colorRamp Optional hint to render the progress bar representing [value] with the
  *   specified [ColorRamp].
+ * @property fallback Used in case any expression has been invalidated.
  */
 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
 public class GoalProgressComplicationData
@@ -1245,7 +1258,10 @@
     dataSource: ComponentName?,
     public val colorRamp: ColorRamp?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public val fallback: GoalProgressComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -1254,15 +1270,15 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * The [DynamicFloat] optionally set by the data source. If present the system will dynamically
      * evaluate this and store the result in [value]. Watch faces can typically ignore this field.
-     *
-     * @hide
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public val valueExpression: DynamicFloat? = valueExpression
 
     /**
@@ -1287,9 +1303,9 @@
          * @param value The value of the goal complication which should be >= 0.
          * @param targetValue The target value. This must be less than [Float.MAX_VALUE].
          * @param contentDescription Defines localized text that briefly describes content of the
-         * complication. This property is used primarily for accessibility. Since some complications
-         * do not have textual representation this attribute can be used for providing such. Please
-         * do not include the word 'complication' in the description.
+         *   complication. This property is used primarily for accessibility. Since some
+         *   complications do not have textual representation this attribute can be used for
+         *   providing such. Please do not include the word 'complication' in the description.
          */
         public constructor(
             value: Float,
@@ -1304,10 +1320,11 @@
          *   evaluated into a value dynamically, and should be >= 0.
          * @param targetValue The target value. This must be less than [Float.MAX_VALUE].
          * @param contentDescription Defines localized text that briefly describes content of the
-         * complication. This property is used primarily for accessibility. Since some complications
-         * do not have textual representation this attribute can be used for providing such. Please
-         * do not include the word 'complication' in the description.
+         *   complication. This property is used primarily for accessibility. Since some
+         *   complications do not have textual representation this attribute can be used for
+         *   providing such. Please do not include the word 'complication' in the description.
          */
+        // TODO(b/269414040): Unhide complication expression APIs.
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         public constructor(
             valueExpression: DynamicFloat,
@@ -1392,6 +1409,7 @@
                 colorRamp,
                 persistencePolicy,
                 displayPolicy,
+                fallback = fallback,
             )
         }
     }
@@ -1440,7 +1458,7 @@
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
             "colorRamp=$colorRamp, persistencePolicy=$persistencePolicy, " +
-            "displayPolicy=$displayPolicy)"
+            "displayPolicy=$displayPolicy, fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() =
@@ -1493,9 +1511,8 @@
  * recommended to choose the [smallImage]. It's best practice for a ComplicationDataSource to
  * specify both a [monochromaticImage] and a [smallImage].
  *
- * A data source that wants to serve a SmallImageComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a SmallImageComplicationData must include the following meta
+ * data in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="WEIGHTED_ELEMENTS"/>
@@ -1536,6 +1553,7 @@
  *   grey box.
  * @property contentDescription The content description field for accessibility. Please do not
  *   include the word 'complication' in the description.
+ * @property fallback Used in case any expression has been invalidated.
  */
 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
 public class WeightedElementsComplicationData
@@ -1552,7 +1570,10 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public val fallback: WeightedElementsComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -1561,7 +1582,8 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * Describes a single value within a [WeightedElementsComplicationData].
@@ -1617,9 +1639,9 @@
      *   to an experience where the color key becomes obvious. The maximum valid size of this list
      *   is provided by [getMaxElements].
      * @param contentDescription Defines localized text that briefly describes content of the
-     * complication. This property is used primarily for accessibility. Since some complications
-     * do not have textual representation this attribute can be used for providing such. Please
-     * do not include the word 'complication' in the description.
+     *   complication. This property is used primarily for accessibility. Since some complications
+     *   do not have textual representation this attribute can be used for providing such. Please do
+     *   not include the word 'complication' in the description.
      */
     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public class Builder(
@@ -1707,7 +1729,8 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
         }
     }
@@ -1755,7 +1778,8 @@
             "text=$text, contentDescription=$contentDescription), " +
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
-            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy)"
+            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy, " +
+            "fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() =
@@ -1795,7 +1819,6 @@
  *
  * A data source that wants to serve a MonochromaticImageComplicationData must include the following
  * meta data in its manifest (NB the value is a comma separated list):
- *
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="ICON"/>
@@ -1810,6 +1833,7 @@
  *   any information to the user, then provide an empty content description. If no content
  *   description is provided, a generic content description will be used instead. Please do not
  *   include the word 'complication' in the description.
+ * @property fallback Used in case any expression has been invalidated.
  */
 public class MonochromaticImageComplicationData
 internal constructor(
@@ -1820,7 +1844,10 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public val fallback: MonochromaticImageComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -1829,7 +1856,8 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * Builder for [MonochromaticImageComplicationData].
@@ -1838,9 +1866,9 @@
      *
      * @param monochromaticImage The [MonochromaticImage] to be displayed
      * @param contentDescription Defines localized text that briefly describes content of the
-     * complication. This property is used primarily for accessibility. Since some complications
-     * do not have textual representation this attribute can be used for providing such. Please
-     * do not include the word 'complication' in the description.
+     *   complication. This property is used primarily for accessibility. Since some complications
+     *   do not have textual representation this attribute can be used for providing such. Please do
+     *   not include the word 'complication' in the description.
      */
     public class Builder(
         private val monochromaticImage: MonochromaticImage,
@@ -1870,7 +1898,8 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
     }
 
@@ -1895,7 +1924,8 @@
             "contentDescription=$contentDescription), " +
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
-            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy)"
+            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy, " +
+            "fallback=$fallback)"
     }
 
     /** @hide */
@@ -1910,9 +1940,8 @@
  *
  * The image is expected to always be displayed.
  *
- * A data source that wants to serve a SmallImageComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a SmallImageComplicationData must include the following meta
+ * data in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="SMALL_IMAGE"/>
@@ -1927,6 +1956,7 @@
  *   any information to the user, then provide an empty content description. If no content
  *   description is provided, a generic content description will be used instead. Please do not
  *   include the word 'complication' in the description.
+ * @property fallback Used in case any expression has been invalidated.
  */
 public class SmallImageComplicationData
 internal constructor(
@@ -1937,7 +1967,10 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public val fallback: SmallImageComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -1946,7 +1979,8 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * Builder for [SmallImageComplicationData].
@@ -1955,9 +1989,9 @@
      *
      * @param smallImage The [SmallImage] to be displayed
      * @param contentDescription Defines localized text that briefly describes content of the
-     * complication. This property is used primarily for accessibility. Since some complications
-     * do not have textual representation this attribute can be used for providing such. Please
-     * do not include the word 'complication' in the description.
+     *   complication. This property is used primarily for accessibility. Since some complications
+     *   do not have textual representation this attribute can be used for providing such. Please do
+     *   not include the word 'complication' in the description.
      */
     public class Builder(
         private val smallImage: SmallImage,
@@ -1987,7 +2021,8 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
     }
 
@@ -2010,7 +2045,8 @@
             "contentDescription=$contentDescription), " +
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
-            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy)"
+            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy, " +
+            "fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() = smallImage.isPlaceholder()
@@ -2031,9 +2067,8 @@
  * part of the watch face or within a complication. The image is large enough to be cover the entire
  * screen. The image may be cropped to fit the watch face or complication.
  *
- * A data source that wants to serve a PhotoImageComplicationData must include the following
- * meta data in its manifest (NB the value is a comma separated list):
- *
+ * A data source that wants to serve a PhotoImageComplicationData must include the following meta
+ * data in its manifest (NB the value is a comma separated list):
  * ```
  * <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
  *    android:value="LARGE_IMAGE"/>
@@ -2049,6 +2084,7 @@
  *   any information to the user, then provide an empty content description. If no content
  *   description is provided, a generic content description will be used instead. Please do not
  *   include the word 'complication' in the description.
+ * @property fallback Used in case any expression has been invalidated.
  */
 public class PhotoImageComplicationData
 internal constructor(
@@ -2059,7 +2095,10 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
+    // TODO(b/269414040): Unhide complication expression APIs.
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public val fallback: PhotoImageComplicationData?,
 ) :
     ComplicationData(
         TYPE,
@@ -2068,7 +2107,8 @@
         validTimeRange = validTimeRange ?: TimeRange.ALWAYS,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = fallback,
     ) {
     /**
      * Builder for [PhotoImageComplicationData].
@@ -2077,9 +2117,9 @@
      *
      * @param photoImage The [Icon] to be displayed
      * @param contentDescription Defines localized text that briefly describes content of the
-     * complication. This property is used primarily for accessibility. Since some complications
-     * do not have textual representation this attribute can be used for providing such. Please
-     * do not include the word 'complication' in the description.
+     *   complication. This property is used primarily for accessibility. Since some complications
+     *   do not have textual representation this attribute can be used for providing such. Please do
+     *   not include the word 'complication' in the description.
      */
     public class Builder(
         private val photoImage: Icon,
@@ -2110,7 +2150,8 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
+                fallback,
             )
     }
 
@@ -2133,7 +2174,8 @@
             "contentDescription=$contentDescription), " +
             "tapActionLostDueToSerialization=$tapActionLostDueToSerialization, " +
             "tapAction=$tapAction, validTimeRange=$validTimeRange, dataSource=$dataSource, " +
-            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy)"
+            "persistencePolicy=$persistencePolicy, displayPolicy=$displayPolicy, " +
+            "fallback=$fallback)"
     }
 
     override fun hasPlaceholderFields() = photoImage.isPlaceholder()
@@ -2191,7 +2233,7 @@
     cachedWireComplicationData: WireComplicationData?,
     dataSource: ComponentName?,
     @ComplicationPersistencePolicy persistencePolicy: Int,
-    @ComplicationDisplayPolicy displayPolicy: Int
+    @ComplicationDisplayPolicy displayPolicy: Int,
 ) :
     ComplicationData(
         TYPE,
@@ -2199,7 +2241,8 @@
         cachedWireComplicationData = cachedWireComplicationData,
         dataSource = dataSource,
         persistencePolicy = persistencePolicy,
-        displayPolicy = displayPolicy
+        displayPolicy = displayPolicy,
+        fallback = null,
     ) {
     /** Builder for [NoPermissionComplicationData]. */
     public class Builder : BaseBuilder<Builder, NoPermissionComplicationData>() {
@@ -2234,7 +2277,7 @@
                 cachedWireComplicationData,
                 dataSource,
                 persistencePolicy,
-                displayPolicy
+                displayPolicy,
             )
     }
 
@@ -2271,305 +2314,167 @@
     }
 }
 
-@Suppress("NewApi")
-internal fun WireComplicationData.toPlaceholderComplicationData(): ComplicationData? {
-    try {
-        // Make sure we use the correct dataSource, persistencePolicy & displayPolicy.
-        val dataSourceCopy = dataSource
-        val persistencePolicyCopy = persistencePolicy
-        val displayPolicyCopy = displayPolicy
-        return when (type) {
-            NoDataComplicationData.TYPE.toWireComplicationType() -> null
-            ShortTextComplicationData.TYPE.toWireComplicationType() -> {
-                ShortTextComplicationData.Builder(
-                        shortText!!.toApiComplicationTextPlaceholderAware(),
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIconPlaceholderAware())
-                        setSmallImage(parseSmallImagePlaceholderAware())
-                        setTitle(shortTitle?.toApiComplicationTextPlaceholderAware())
-                        setDataSource(dataSourceCopy)
-                        setPersistencePolicy(persistencePolicyCopy)
-                        setDisplayPolicy(displayPolicyCopy)
-                    }
-                    .build()
+internal fun WireComplicationData.toPlaceholderComplicationData(): ComplicationData? =
+    when (type) {
+        NoDataComplicationData.TYPE.toWireComplicationType() -> null
+        EmptyComplicationData.TYPE.toWireComplicationType() -> null
+        NotConfiguredComplicationData.TYPE.toWireComplicationType() -> null
+        else ->
+            toApiComplicationData(placeholderAware = true).let {
+                if (it is NoDataComplicationData) null else it
             }
-            LongTextComplicationData.TYPE.toWireComplicationType() -> {
-                LongTextComplicationData.Builder(
-                        longText!!.toApiComplicationTextPlaceholderAware(),
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIconPlaceholderAware())
-                        setSmallImage(parseSmallImagePlaceholderAware())
-                        setTitle(longTitle?.toApiComplicationTextPlaceholderAware())
-                        setDataSource(dataSourceCopy)
-                        setPersistencePolicy(persistencePolicyCopy)
-                        setDisplayPolicy(displayPolicyCopy)
-                    }
-                    .build()
-            }
-            RangedValueComplicationData.TYPE.toWireComplicationType() ->
-                RangedValueComplicationData.Builder(
-                        value = rangedValue,
-                        valueExpression = rangedValueExpression,
-                        min = rangedMinValue,
-                        max = rangedMaxValue,
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIconPlaceholderAware())
-                        setSmallImage(parseSmallImagePlaceholderAware())
-                        setTitle(shortTitle?.toApiComplicationTextPlaceholderAware())
-                        setText(shortText?.toApiComplicationTextPlaceholderAware())
-                        setDataSource(dataSourceCopy)
-                        colorRamp?.let { setColorRamp(ColorRamp(it, isColorRampInterpolated!!)) }
-                        setPersistencePolicy(persistencePolicyCopy)
-                        setDisplayPolicy(displayPolicyCopy)
-                        setValueType(rangedValueType)
-                    }
-                    .build()
-            MonochromaticImageComplicationData.TYPE.toWireComplicationType() ->
-                MonochromaticImageComplicationData(
-                    parseIconPlaceholderAware()!!,
-                    contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY,
-                    tapAction,
-                    parseTimeRange(),
-                    this,
-                    dataSourceCopy,
-                    persistencePolicyCopy,
-                    displayPolicyCopy
-                )
-            SmallImageComplicationData.TYPE.toWireComplicationType() ->
-                SmallImageComplicationData(
-                    parseSmallImagePlaceholderAware()!!,
-                    contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY,
-                    tapAction,
-                    parseTimeRange(),
-                    this,
-                    dataSourceCopy,
-                    persistencePolicyCopy,
-                    displayPolicyCopy
-                )
-            PhotoImageComplicationData.TYPE.toWireComplicationType() ->
-                PhotoImageComplicationData(
-                    parseLargeImagePlaceholderAware()!!,
-                    contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY,
-                    tapAction,
-                    parseTimeRange(),
-                    this,
-                    dataSourceCopy,
-                    persistencePolicyCopy,
-                    displayPolicyCopy
-                )
-            GoalProgressComplicationData.TYPE.toWireComplicationType() ->
-                GoalProgressComplicationData.Builder(
-                        value = rangedValue,
-                        valueExpression = rangedValueExpression,
-                        targetValue = targetValue,
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIconPlaceholderAware())
-                        setSmallImage(parseSmallImagePlaceholderAware())
-                        setTitle(shortTitle?.toApiComplicationTextPlaceholderAware())
-                        setText(shortText?.toApiComplicationTextPlaceholderAware())
-                        setDataSource(dataSourceCopy)
-                        colorRamp?.let { setColorRamp(ColorRamp(it, isColorRampInterpolated!!)) }
-                        setPersistencePolicy(persistencePolicyCopy)
-                        setDisplayPolicy(displayPolicyCopy)
-                    }
-                    .build()
-            WeightedElementsComplicationData.TYPE.toWireComplicationType() ->
-                WeightedElementsComplicationData.Builder(
-                        elements =
-                            if (elementWeights!!.isEmpty()) {
-                                WeightedElementsComplicationData.PLACEHOLDER
-                            } else {
-                                val elementWeights = this.elementWeights!!
-                                val elementColors = this.elementColors!!
-                                require(elementWeights.size == elementColors.size) {
-                                    "elementWeights and elementColors must have the same size"
-                                }
-                                elementWeights
-                                    .mapIndexed { index, weight ->
-                                        WeightedElementsComplicationData.Element(
-                                            weight,
-                                            elementColors[index]
-                                        )
-                                    }
-                                    .toList()
-                            },
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setElementBackgroundColor(elementBackgroundColor)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIconPlaceholderAware())
-                        setSmallImage(parseSmallImagePlaceholderAware())
-                        setTitle(shortTitle?.toApiComplicationTextPlaceholderAware())
-                        setText(shortText?.toApiComplicationTextPlaceholderAware())
-                        setDataSource(dataSourceCopy)
-                        setPersistencePolicy(persistencePolicyCopy)
-                        setDisplayPolicy(displayPolicyCopy)
-                    }
-                    .build()
-            else -> null
-        }
-    } catch (e: Exception) {
-        Log.e(
-            TAG,
-            "WireComplicationData.toPlaceholderComplicationData failed for " +
-                toStringNoRedaction(),
-            e
-        )
-        throw e
     }
-}
 
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public fun WireComplicationData.toApiComplicationData(): ComplicationData =
+    toApiComplicationData(placeholderAware = false)
+
 @Suppress("NewApi")
-public fun WireComplicationData.toApiComplicationData(): ComplicationData {
+private fun WireComplicationData.toApiComplicationData(
+    placeholderAware: Boolean
+): ComplicationData {
     try {
         return when (type) {
-            NoDataComplicationData.TYPE.toWireComplicationType() -> {
-                placeholder?.toPlaceholderComplicationData()?.let {
-                    NoDataComplicationData(it, this@toApiComplicationData)
-                }
-                    ?: NoDataComplicationData(null, this@toApiComplicationData)
-            }
+            NoDataComplicationData.TYPE.toWireComplicationType() ->
+                NoDataComplicationData(placeholder?.toPlaceholderComplicationData(), this)
             EmptyComplicationData.TYPE.toWireComplicationType() -> EmptyComplicationData()
             NotConfiguredComplicationData.TYPE.toWireComplicationType() ->
                 NotConfiguredComplicationData()
             ShortTextComplicationData.TYPE.toWireComplicationType() ->
-                ShortTextComplicationData.Builder(
-                        shortText!!.toApiComplicationText(),
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setTitle(shortTitle?.toApiComplicationText())
-                        setMonochromaticImage(parseIcon())
-                        setSmallImage(parseSmallImage())
-                    }
-                    .build()
+                ShortTextComplicationData(
+                    text = shortText!!.toApiComplicationText(placeholderAware),
+                    title = shortTitle?.toApiComplicationText(placeholderAware),
+                    monochromaticImage = parseIcon(placeholderAware),
+                    smallImage = parseSmallImage(placeholderAware),
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             LongTextComplicationData.TYPE.toWireComplicationType() ->
-                LongTextComplicationData.Builder(
-                        longText!!.toApiComplicationText(),
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setTitle(longTitle?.toApiComplicationText())
-                        setMonochromaticImage(parseIcon())
-                        setSmallImage(parseSmallImage())
-                    }
-                    .build()
+                LongTextComplicationData(
+                    text = longText!!.toApiComplicationText(placeholderAware),
+                    title = longTitle?.toApiComplicationText(placeholderAware),
+                    monochromaticImage = parseIcon(placeholderAware),
+                    smallImage = parseSmallImage(placeholderAware),
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             RangedValueComplicationData.TYPE.toWireComplicationType() ->
-                RangedValueComplicationData.Builder(
-                        value = rangedValue,
-                        valueExpression = rangedValueExpression,
-                        min = rangedMinValue,
-                        max = rangedMaxValue,
-                        contentDescription = contentDescription?.toApiComplicationText()
-                                ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIcon())
-                        setSmallImage(parseSmallImage())
-                        setTitle(shortTitle?.toApiComplicationText())
-                        setText(shortText?.toApiComplicationText())
-                        colorRamp?.let { setColorRamp(ColorRamp(it, isColorRampInterpolated!!)) }
-                        setValueType(rangedValueType)
-                    }
-                    .build()
+                RangedValueComplicationData(
+                    value = rangedValue,
+                    valueExpression = rangedValueExpression,
+                    min = rangedMinValue,
+                    max = rangedMaxValue,
+                    monochromaticImage = parseIcon(placeholderAware),
+                    smallImage = parseSmallImage(placeholderAware),
+                    title = shortTitle?.toApiComplicationText(placeholderAware),
+                    text = shortText?.toApiComplicationText(placeholderAware),
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    colorRamp = colorRamp?.let { ColorRamp(it, isColorRampInterpolated!!) },
+                    valueType = rangedValueType,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             MonochromaticImageComplicationData.TYPE.toWireComplicationType() ->
-                MonochromaticImageComplicationData.Builder(
-                        parseIcon()!!,
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                    }
-                    .build()
+                MonochromaticImageComplicationData(
+                    monochromaticImage = parseIcon(placeholderAware)!!,
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             SmallImageComplicationData.TYPE.toWireComplicationType() ->
-                SmallImageComplicationData.Builder(
-                        parseSmallImage()!!,
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                    }
-                    .build()
+                SmallImageComplicationData(
+                    smallImage = parseSmallImage(placeholderAware)!!,
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             PhotoImageComplicationData.TYPE.toWireComplicationType() ->
-                PhotoImageComplicationData.Builder(
-                        largeImage!!,
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                    }
-                    .build()
+                PhotoImageComplicationData(
+                    photoImage = parseLargeImage(placeholderAware)!!,
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             NoPermissionComplicationData.TYPE.toWireComplicationType() ->
-                NoPermissionComplicationData.Builder()
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setMonochromaticImage(parseIcon())
-                        setSmallImage(parseSmallImage())
-                        setTitle(shortTitle?.toApiComplicationText())
-                        setText(shortText?.toApiComplicationText())
-                    }
-                    .build()
+                NoPermissionComplicationData(
+                    text = shortText?.toApiComplicationText(),
+                    title = shortTitle?.toApiComplicationText(),
+                    monochromaticImage = parseIcon(),
+                    smallImage = parseSmallImage(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                )
             GoalProgressComplicationData.TYPE.toWireComplicationType() ->
-                GoalProgressComplicationData.Builder(
-                        value = rangedValue,
-                        valueExpression = rangedValueExpression,
-                        targetValue = targetValue,
-                        contentDescription = contentDescription?.toApiComplicationText()
-                                ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIcon())
-                        setSmallImage(parseSmallImage())
-                        setTitle(shortTitle?.toApiComplicationText())
-                        setText(shortText?.toApiComplicationText())
-                        colorRamp?.let { setColorRamp(ColorRamp(it, isColorRampInterpolated!!)) }
-                    }
-                    .build()
-            WeightedElementsComplicationData.TYPE.toWireComplicationType() -> {
-                val elementWeights = this.elementWeights!!
-                val elementColors = this.elementColors!!
-                require(elementWeights.size == elementColors.size) {
-                    "elementWeights and elementColors must have the same size"
-                }
-                WeightedElementsComplicationData.Builder(
-                        elements =
+                GoalProgressComplicationData(
+                    value = rangedValue,
+                    valueExpression = rangedValueExpression,
+                    targetValue = targetValue,
+                    monochromaticImage = parseIcon(placeholderAware),
+                    smallImage = parseSmallImage(placeholderAware),
+                    title = shortTitle?.toApiComplicationText(placeholderAware),
+                    text = shortText?.toApiComplicationText(placeholderAware),
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    colorRamp = colorRamp?.let { ColorRamp(it, isColorRampInterpolated!!) },
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
+            WeightedElementsComplicationData.TYPE.toWireComplicationType() ->
+                WeightedElementsComplicationData(
+                    elements =
+                        if (placeholderAware && elementWeights!!.isEmpty()) {
+                            WeightedElementsComplicationData.PLACEHOLDER
+                        } else {
+                            val elementWeights = this.elementWeights!!
+                            val elementColors = this.elementColors!!
+                            require(elementWeights.size == elementColors.size) {
+                                "elementWeights and elementColors must have the same size"
+                            }
                             elementWeights
                                 .mapIndexed { index, weight ->
                                     WeightedElementsComplicationData.Element(
@@ -2577,21 +2482,23 @@
                                         elementColors[index]
                                     )
                                 }
-                                .toList(),
-                        contentDescription?.toApiComplicationText() ?: ComplicationText.EMPTY
-                    )
-                    .apply {
-                        setCommon(this@toApiComplicationData)
-                        setElementBackgroundColor(elementBackgroundColor)
-                        setTapAction(tapAction)
-                        setValidTimeRange(parseTimeRange())
-                        setMonochromaticImage(parseIcon())
-                        setSmallImage(parseSmallImage())
-                        setTitle(shortTitle?.toApiComplicationText())
-                        setText(shortText?.toApiComplicationText())
-                    }
-                    .build()
-            }
+                                .toList()
+                        },
+                    elementBackgroundColor = elementBackgroundColor,
+                    monochromaticImage = parseIcon(placeholderAware),
+                    smallImage = parseSmallImage(placeholderAware),
+                    title = shortTitle?.toApiComplicationText(placeholderAware),
+                    text = shortText?.toApiComplicationText(placeholderAware),
+                    contentDescription = contentDescription?.toApiComplicationText()
+                            ?: ComplicationText.EMPTY,
+                    tapAction = tapAction,
+                    validTimeRange = parseTimeRange(),
+                    cachedWireComplicationData = this,
+                    dataSource = dataSource,
+                    persistencePolicy = persistencePolicy,
+                    displayPolicy = displayPolicy,
+                    fallback = placeholder?.toTypedApiComplicationData(),
+                )
             else -> NoDataComplicationData()
         }
     } catch (e: Exception) {
@@ -2604,6 +2511,11 @@
     }
 }
 
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@Suppress("UNCHECKED_CAST")
+public fun <T : ComplicationData> WireComplicationData.toTypedApiComplicationData(): T =
+    toApiComplicationData() as T
+
 private fun WireComplicationData.parseTimeRange() =
     if ((startDateTimeMillis == 0L) and (endDateTimeMillis == Long.MAX_VALUE)) {
         null
@@ -2614,36 +2526,18 @@
         )
     }
 
-private fun WireComplicationData.parseIcon() =
+private fun WireComplicationData.parseIcon(placeholderAware: Boolean = false) =
     icon?.let {
-        MonochromaticImage.Builder(it).apply { setAmbientImage(burnInProtectionIcon) }.build()
-    }
-
-private fun WireComplicationData.parseIconPlaceholderAware() =
-    icon?.let {
-        if (it.isPlaceholder()) {
+        if (placeholderAware && it.isPlaceholder()) {
             MonochromaticImage.PLACEHOLDER
         } else {
             MonochromaticImage.Builder(it).apply { setAmbientImage(burnInProtectionIcon) }.build()
         }
     }
 
-private fun WireComplicationData.parseSmallImage() =
+private fun WireComplicationData.parseSmallImage(placeholderAware: Boolean = false) =
     smallImage?.let {
-        val imageStyle =
-            when (smallImageStyle) {
-                WireComplicationData.IMAGE_STYLE_ICON -> SmallImageType.ICON
-                WireComplicationData.IMAGE_STYLE_PHOTO -> SmallImageType.PHOTO
-                else -> SmallImageType.PHOTO
-            }
-        SmallImage.Builder(it, imageStyle)
-            .apply { setAmbientImage(burnInProtectionSmallImage) }
-            .build()
-    }
-
-private fun WireComplicationData.parseSmallImagePlaceholderAware() =
-    smallImage?.let {
-        if (it.isPlaceholder()) {
+        if (placeholderAware && it.isPlaceholder()) {
             SmallImage.PLACEHOLDER
         } else {
             val imageStyle =
@@ -2658,9 +2552,9 @@
         }
     }
 
-private fun WireComplicationData.parseLargeImagePlaceholderAware() =
+private fun WireComplicationData.parseLargeImage(placeholderAware: Boolean = false) =
     largeImage?.let {
-        if (it.isPlaceholder()) {
+        if (placeholderAware && it.isPlaceholder()) {
             PhotoImageComplicationData.PLACEHOLDER
         } else {
             it
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Text.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Text.kt
index 60db4fe..de0c253 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Text.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Text.kt
@@ -71,10 +71,7 @@
     /** @hide */
     @RestrictTo(RestrictTo.Scope.SUBCLASSES) public fun getTimeDependentText(): TimeDependentText
 
-    /**
-     * Converts this value to [WireComplicationText] object used for serialization.
-     *
-     */
+    /** Converts this value to [WireComplicationText] object used for serialization. */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public fun toWireComplicationText(): WireComplicationText
 
@@ -548,12 +545,10 @@
 }
 
 /** Converts a [WireComplicationText] into an equivalent [ComplicationText] instead. */
-internal fun WireComplicationText.toApiComplicationText(): ComplicationText =
-    DelegatingComplicationText(this)
-
-/** Converts a [WireComplicationText] into an equivalent [ComplicationText] instead. */
-internal fun WireComplicationText.toApiComplicationTextPlaceholderAware(): ComplicationText =
-    if (isPlaceholder) {
+internal fun WireComplicationText.toApiComplicationText(
+    placeholderAware: Boolean = false
+): ComplicationText =
+    if (placeholderAware && isPlaceholder) {
         ComplicationText.PLACEHOLDER
     } else {
         DelegatingComplicationText(this)
@@ -615,8 +610,8 @@
  * A [ComplicationText] where the system evaluates a [DynamicString] on behalf of the watch face. By
  * the time this reaches the watch face's Renderer, it'll have been converted to a plain
  * ComplicationText.
- *
  */
+// TODO(b/269414040): Unhide complication expression APIs.
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class ComplicationTextExpression(public val expression: DynamicString) : ComplicationText {
     private val delegate = DelegatingComplicationText(WireComplicationText(expression))
diff --git a/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataTest.kt b/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataTest.kt
index 3f25f2a..588241b 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataTest.kt
@@ -25,15 +25,20 @@
 import android.support.wearable.complications.ComplicationText.plainText
 import androidx.test.core.app.ApplicationProvider
 import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicString
 import androidx.wear.watchface.complications.data.SharedRobolectricTestRunner
+import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert
 import org.junit.Assert.assertThrows
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @RunWith(SharedRobolectricTestRunner::class)
 public class ComplicationDataTest {
+    @get:Rule val expect = Expect.create()
+
     private val mPendingIntent: PendingIntent? =
         PendingIntent.getBroadcast(
             ApplicationProvider.getApplicationContext(),
@@ -1069,6 +1074,54 @@
         assertThat(entry.placeholder!!.type).isEqualTo(ComplicationData.TYPE_LONG_TEXT)
     }
 
+    enum class HasExpressionWithExpressionScenario(val data: ComplicationData) {
+        RANGED_VALUE(
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA)
+                .setRangedValueExpression(DynamicFloat.constant(1f))
+                .build()
+        ),
+        LONG_TEXT(
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA)
+                .setLongText(ComplicationText(DynamicString.constant("Long Text")))
+                .build()
+        ),
+        LONG_TITLE(
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA)
+                .setLongTitle(ComplicationText(DynamicString.constant("Long Title")))
+                .build()
+        ),
+        SHORT_TEXT(
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA)
+                .setShortText(ComplicationText(DynamicString.constant("Short Text")))
+                .build()
+        ),
+        SHORT_TITLE(
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA)
+                .setShortTitle(ComplicationText(DynamicString.constant("Short Title")))
+                .build()
+        ),
+        CONTENT_DESCRIPTION(
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA)
+                .setContentDescription(ComplicationText(DynamicString.constant("Description")))
+                .build()
+        ),
+    }
+
+    @Test
+    fun hasExpression_withExpression_returnsTrue() {
+        for (scenario in HasExpressionWithExpressionScenario.values()) {
+            expect.withMessage(scenario.name).that(scenario.data.hasExpression()).isTrue()
+        }
+    }
+
+    @Test
+    fun hasExpression_withoutExpression_returnsFalse() {
+        val data =
+            ComplicationData.Builder(ComplicationData.TYPE_NO_DATA).setRangedValue(10f).build()
+
+        assertThat(data.hasExpression()).isFalse()
+    }
+
     private companion object {
         val TEST_CONTENT_DESCRIPTION: CharSequence = "This is a test description!"
         const val TEST_LONG_TITLE = "what a long title such a long title"
diff --git a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt
index 05f6f9f..c913c25 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt
@@ -26,7 +26,6 @@
 import androidx.wear.protolayout.expression.pipeline.StateStore
 import androidx.wear.protolayout.expression.pipeline.TimeGateway
 import androidx.wear.watchface.complications.data.ComplicationDataExpressionEvaluator.Companion.INVALID_DATA
-import androidx.wear.watchface.complications.data.ComplicationDataExpressionEvaluator.Companion.hasExpression
 import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertThat
 import java.time.Instant
@@ -59,10 +58,14 @@
 
     @Test
     fun evaluate_noExpression_returnsUnevaluated() = runBlocking {
+        val data =
+            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
+                .setRangedValue(10f)
+                .build()
+
         val evaluator = ComplicationDataExpressionEvaluator()
 
-        assertThat(evaluator.evaluate(DATA_WITH_NO_EXPRESSION).firstOrNull())
-            .isEqualTo(DATA_WITH_NO_EXPRESSION)
+        assertThat(evaluator.evaluate(data).firstOrNull()).isEqualTo(data)
     }
 
     /**
@@ -203,8 +206,7 @@
         for (scenario in DataWithExpressionScenario.values()) {
             // Defensive copy due to in-place evaluation.
             val expressed = WireComplicationData.Builder(scenario.expressed).build()
-            val stateStore =
-                StateStore(mapOf())
+            val stateStore = StateStore(mapOf())
             val evaluator = ComplicationDataExpressionEvaluator(stateStore)
             val allEvaluations =
                 evaluator
@@ -294,57 +296,7 @@
             )
     }
 
-    enum class HasExpressionDataWithExpressionScenario(val data: WireComplicationData) {
-        RANGED_VALUE(
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setRangedValueExpression(DynamicFloat.constant(1f))
-                .build()
-        ),
-        LONG_TEXT(
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setLongText(WireComplicationText(DynamicString.constant("Long Text")))
-                .build()
-        ),
-        LONG_TITLE(
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setLongTitle(WireComplicationText(DynamicString.constant("Long Title")))
-                .build()
-        ),
-        SHORT_TEXT(
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setShortText(WireComplicationText(DynamicString.constant("Short Text")))
-                .build()
-        ),
-        SHORT_TITLE(
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setShortTitle(WireComplicationText(DynamicString.constant("Short Title")))
-                .build()
-        ),
-        CONTENT_DESCRIPTION(
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setContentDescription(WireComplicationText(DynamicString.constant("Description")))
-                .build()
-        ),
-    }
-
-    @Test
-    fun hasExpression_dataWithExpression_returnsTrue() {
-        for (scenario in HasExpressionDataWithExpressionScenario.values()) {
-            expect.withMessage(scenario.name).that(hasExpression(scenario.data)).isTrue()
-        }
-    }
-
-    @Test
-    fun hasExpression_dataWithoutExpression_returnsFalse() {
-        assertThat(hasExpression(DATA_WITH_NO_EXPRESSION)).isFalse()
-    }
-
     private companion object {
-        val DATA_WITH_NO_EXPRESSION =
-            WireComplicationData.Builder(WireComplicationData.TYPE_NO_DATA)
-                .setRangedValue(10f)
-                .build()
-
         /** Converts `[{a: A}, {b: B}, {c: C}]` to `[{a: A}, {a: A, b: B}, {a: A, b: B, c: C}]`. */
         fun <K, V> aggregate(vararg maps: Map<K, V>): List<Map<K, V>> =
             maps.fold(listOf()) { acc, map -> acc + ((acc.lastOrNull() ?: mapOf()) + map) }
diff --git a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
index f75fff1..356a70f 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
@@ -163,7 +163,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=1, " +
-                    "displayPolicy=1)"
+                    "displayPolicy=1, fallback=null)"
             )
     }
 
@@ -217,7 +217,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -261,7 +261,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -316,7 +316,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -367,7 +367,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, colorRamp=null, " +
-                    "persistencePolicy=0, displayPolicy=0)"
+                    "persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -421,7 +421,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), dataSource=" +
                     "ComponentInfo{com.pkg_a/com.a}, colorRamp=null, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -471,7 +471,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, colorRamp=null, " +
-                    "persistencePolicy=0, displayPolicy=0)"
+                    "persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -535,7 +535,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, colorRamp=null, " +
-                    "persistencePolicy=0, displayPolicy=0)"
+                    "persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -582,7 +582,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, colorRamp=null, " +
-                    "persistencePolicy=0, displayPolicy=0)"
+                    "persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -633,7 +633,7 @@
                     "startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, colorRamp=null, " +
-                    "persistencePolicy=0, displayPolicy=0)"
+                    "persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -683,7 +683,7 @@
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, " +
                     "colorRamp=ColorRamp(colors=[-65536, -16711936, -16776961], " +
-                    "interpolated=true), persistencePolicy=0, displayPolicy=0)"
+                    "interpolated=true), persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -746,7 +746,7 @@
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, " +
                     "colorRamp=ColorRamp(colors=[-65536, -16711936, -16776961], " +
-                    "interpolated=true), persistencePolicy=0, displayPolicy=0)"
+                    "interpolated=true), persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -801,7 +801,7 @@
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, " +
                     "colorRamp=ColorRamp(colors=[-65536, -16711936, -16776961], " +
-                    "interpolated=true), persistencePolicy=0, displayPolicy=0)"
+                    "interpolated=true), persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
     }
 
@@ -874,7 +874,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -943,7 +943,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -983,7 +983,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -1023,7 +1023,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -1094,7 +1094,7 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
     }
 
@@ -1227,7 +1227,8 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1279,7 +1280,8 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1340,7 +1342,8 @@
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, colorRamp=null, " +
                     "persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1401,7 +1404,7 @@
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, " +
                     "colorRamp=ColorRamp(colors=[-65536, -16711936, -16776961], " +
-                    "interpolated=false), persistencePolicy=0, displayPolicy=0), " +
+                    "interpolated=false), persistencePolicy=0, displayPolicy=0, fallback=null), " +
                     "tapActionLostDueToSerialization=false, " +
                     "tapAction=null, validTimeRange=TimeRange(startDateTimeMillis=" +
                     "-1000000000-01-01T00:00:00Z, " +
@@ -1466,7 +1469,8 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1532,7 +1536,8 @@
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, " +
                     "colorRamp=ColorRamp(colors=[-65536, -16711936, -16776961], " +
                     "interpolated=true), persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1583,7 +1588,8 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1635,7 +1641,8 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -1686,7 +1693,8 @@
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "dataSource=ComponentInfo{com.pkg_a/com.a}, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(startDateTimeMillis=-1000000000-01-01T00:00:00Z, " +
                     "endDateTimeMillis=+1000000000-12-31T23:59:59.999999999Z), " +
                     "persistencePolicy=0, displayPolicy=0)"
@@ -2856,7 +2864,7 @@
                     "mSurroundingText=REDACTED, mTimeDependentText=null, mExpression=null}, " +
                     "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(REDACTED), dataSource=null, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
         assertThat(data.asWireComplicationData().toString())
             .isEqualTo("ComplicationData{mType=3, mFields=REDACTED}")
@@ -2882,7 +2890,7 @@
                     "mSurroundingText=REDACTED, mTimeDependentText=null, mExpression=null}), " +
                     "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(REDACTED), dataSource=null, persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
         assertThat(data.asWireComplicationData().toString())
             .isEqualTo("ComplicationData{mType=4, mFields=REDACTED}")
@@ -2911,7 +2919,7 @@
                     "ComplicationText{mSurroundingText=REDACTED, mTimeDependentText=null, " +
                     "mExpression=null}), tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(REDACTED), dataSource=null, colorRamp=null, " +
-                    "persistencePolicy=0, displayPolicy=0)"
+                    "persistencePolicy=0, displayPolicy=0, fallback=null)"
             )
         assertThat(data.asWireComplicationData().toString())
             .isEqualTo("ComplicationData{mType=5, mFields=REDACTED}")
@@ -2940,7 +2948,7 @@
                     "tapActionLostDueToSerialization=false, tapAction=null, validTimeRange=" +
                     "TimeRange(REDACTED), dataSource=null, colorRamp=ColorRamp(colors=[-65536, " +
                     "-16711936, -16776961], interpolated=true), persistencePolicy=0, " +
-                    "displayPolicy=0)"
+                    "displayPolicy=0, fallback=null)"
             )
         assertThat(data.asWireComplicationData().toString())
             .isEqualTo("ComplicationData{mType=13, mFields=REDACTED}")
@@ -2967,7 +2975,8 @@
                     "mTimeDependentText=null, mExpression=null}), " +
                     "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(REDACTED), dataSource=null, persistencePolicy=0, " +
-                    "displayPolicy=0), tapActionLostDueToSerialization=false, tapAction=null, " +
+                    "displayPolicy=0, fallback=null), " +
+                    "tapActionLostDueToSerialization=false, tapAction=null, " +
                     "validTimeRange=TimeRange(REDACTED), persistencePolicy=0, displayPolicy=0)"
             )
         assertThat(data.asWireComplicationData().toString())
diff --git a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
index d777b03..32cdbdc 100644
--- a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
+++ b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
@@ -1835,6 +1835,7 @@
         EditorService.globalEditorService.unregisterObserver(observerId)
     }
 
+    @SdkSuppress(maxSdkVersion = 32) // b/275361339
     @Test
     @Suppress("Deprecation") // userStyleSettings
     public fun commit_headless() {
@@ -1886,6 +1887,7 @@
         EditorService.globalEditorService.unregisterObserver(observerId)
     }
 
+    @SdkSuppress(maxSdkVersion = 32) // b/275361339
     @SuppressLint("NewApi")
     @Suppress("Deprecation") // userStyleSettings
     @Test
diff --git a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/WatchFaceServiceAndroidTest.kt b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/WatchFaceServiceAndroidTest.kt
index 8c7e17e..eafefe5 100644
--- a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/WatchFaceServiceAndroidTest.kt
+++ b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/WatchFaceServiceAndroidTest.kt
@@ -21,6 +21,7 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
 import androidx.wear.watchface.control.InteractiveInstanceManager
 import androidx.wear.watchface.style.UserStyleSchema
 import androidx.wear.watchface.style.UserStyleSetting
@@ -38,6 +39,7 @@
         InteractiveInstanceManager.setParameterlessEngine(null)
     }
 
+    @SdkSuppress(maxSdkVersion = 32) // b/275361339
     @Test
     fun measuresWatchFaceIconsFromCustomContext() {
         val context: Context = ApplicationProvider.getApplicationContext()
diff --git a/wear/wear-phone-interactions/src/main/stableAidlImports/android/os/Bundle.aidl b/wear/wear-phone-interactions/src/main/stableAidlImports/android/os/Bundle.aidl
deleted file mode 100644
index 9642d31..0000000
--- a/wear/wear-phone-interactions/src/main/stableAidlImports/android/os/Bundle.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.os;
-
-@JavaOnlyStableParcelable parcelable Bundle;
diff --git a/wear/wear/src/main/java/androidx/wear/widget/SwipeDismissTransitionHelper.java b/wear/wear/src/main/java/androidx/wear/widget/SwipeDismissTransitionHelper.java
index 7a82c04..3953ac3 100644
--- a/wear/wear/src/main/java/androidx/wear/widget/SwipeDismissTransitionHelper.java
+++ b/wear/wear/src/main/java/androidx/wear/widget/SwipeDismissTransitionHelper.java
@@ -257,10 +257,14 @@
         mCompositingPaint.setColorFilter(null);
         mLayout.setLayerType(View.LAYER_TYPE_NONE, null);
         mLayout.setClipToOutline(false);
-        getOriginalParentView().setBackground(mPrevParentBackground);
+
+        // Restoring previous background
+        ViewGroup originalParentView = getOriginalParentView();
+        if (originalParentView != null) {
+            originalParentView.setBackground(mPrevParentBackground);
+        }
         mPrevParentBackground = null;
     }
-
     private Drawable generateScrimBackgroundDrawable(int width, int height) {
         ShapeDrawable shape = new ShapeDrawable(new RectShape());
         shape.setBounds(0, 0, width, height);
diff --git a/window/extensions/extensions/api/current.ignore b/window/extensions/extensions/api/current.ignore
deleted file mode 100644
index c3f19a2..0000000
--- a/window/extensions/extensions/api/current.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedDeprecatedMethod: androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener(android.content.Context, java.util.function.Consumer<androidx.window.extensions.layout.WindowLayoutInfo>):
-    Removed deprecated method androidx.window.extensions.layout.WindowLayoutComponent.addWindowLayoutInfoListener(android.content.Context,java.util.function.Consumer<androidx.window.extensions.layout.WindowLayoutInfo>)
diff --git a/window/extensions/extensions/api/restricted_current.ignore b/window/extensions/extensions/api/restricted_current.ignore
deleted file mode 100644
index c3f19a2..0000000
--- a/window/extensions/extensions/api/restricted_current.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedDeprecatedMethod: androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener(android.content.Context, java.util.function.Consumer<androidx.window.extensions.layout.WindowLayoutInfo>):
-    Removed deprecated method androidx.window.extensions.layout.WindowLayoutComponent.addWindowLayoutInfoListener(android.content.Context,java.util.function.Consumer<androidx.window.extensions.layout.WindowLayoutInfo>)
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt
deleted file mode 100644
index e8fc72a..0000000
--- a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * Copyright 2022 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.window.embedding
-
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.graphics.Rect
-import android.os.Build
-import androidx.annotation.RequiresApi
-import androidx.test.core.app.ApplicationProvider
-import androidx.window.embedding.EmbeddingAspectRatio.Companion.ALWAYS_ALLOW
-import androidx.window.embedding.EmbeddingAspectRatio.Companion.ALWAYS_DISALLOW
-import androidx.window.embedding.EmbeddingAspectRatio.Companion.ratio
-import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.BOTTOM_TO_TOP
-import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.LEFT_TO_RIGHT
-import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.LOCALE
-import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.RIGHT_TO_LEFT
-import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.TOP_TO_BOTTOM
-import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT
-import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
-import androidx.window.embedding.SplitRule.Companion.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW
-import androidx.window.embedding.SplitRule.Companion.SPLIT_MIN_DIMENSION_DP_DEFAULT
-import androidx.window.embedding.SplitRule.FinishBehavior.Companion.ADJACENT
-import androidx.window.embedding.SplitRule.FinishBehavior.Companion.ALWAYS
-import androidx.window.embedding.SplitRule.FinishBehavior.Companion.NEVER
-import androidx.window.test.R
-import junit.framework.TestCase.assertNull
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertThrows
-import org.junit.Assert.assertTrue
-import org.junit.Assume.assumeTrue
-import org.junit.Before
-import org.junit.Test
-
-/**
- * Tests creation of all embedding rule types via builders and from XML.
- * @see SplitPairRule
- * @see SplitRule
- * @see ActivityRule
- */
-class EmbeddingRuleConstructionTests {
-    private val application = ApplicationProvider.getApplicationContext<Context>()
-    private val ruleController = RuleController.getInstance(application)
-    private val density = application.resources.displayMetrics.density
-    private lateinit var validBounds: Rect
-    private lateinit var invalidBounds: Rect
-
-    @Before
-    fun setUp() {
-        validBounds = minValidWindowBounds()
-        invalidBounds = almostValidWindowBounds()
-        ruleController.clearRules()
-    }
-
-    /**
-     * Verifies that default params are set correctly when reading {@link SplitPairRule} from XML.
-     */
-    @Test
-    fun testDefaults_SplitPairRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_default_split_pair_rule)
-        assertEquals(1, rules.size)
-        val rule: SplitPairRule = rules.first() as SplitPairRule
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
-            .setLayoutDirection(LOCALE)
-            .build()
-        assertNull(rule.tag)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
-        assertEquals(NEVER, rule.finishPrimaryWithSecondary)
-        assertEquals(ALWAYS, rule.finishSecondaryWithPrimary)
-        assertEquals(false, rule.clearTop)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertTrue(rule.checkParentBounds(density, validBounds))
-        assertFalse(rule.checkParentBounds(density, invalidBounds))
-    }
-
-    /**
-     * Verifies that params are set correctly when reading {@link SplitPairRule} from XML.
-     * @see R.xml.test_split_config_custom_split_pair_rule for customized value.
-     */
-    @Test
-    fun testCustom_SplitPairRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_custom_split_pair_rule)
-        assertEquals(1, rules.size)
-        val rule: SplitPairRule = rules.first() as SplitPairRule
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.1f))
-            .setLayoutDirection(RIGHT_TO_LEFT)
-            .build()
-        assertEquals("rule2", rule.tag)
-        assertEquals(123, rule.minWidthDp)
-        assertEquals(456, rule.minHeightDp)
-        assertEquals(789, rule.minSmallestWidthDp)
-        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
-        assertEquals(ALWAYS_DISALLOW, rule.maxAspectRatioInLandscape)
-        assertEquals(ALWAYS, rule.finishPrimaryWithSecondary)
-        assertEquals(NEVER, rule.finishSecondaryWithPrimary)
-        assertEquals(true, rule.clearTop)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-    }
-
-    /** Verifies that horizontal layout are set correctly when reading [SplitPairRule] from XML. */
-    @Test
-    fun testHorizontalLayout_SplitPairRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_split_pair_rule_horizontal_layout)
-        assertEquals(1, rules.size)
-        val rule: SplitPairRule = rules.first() as SplitPairRule
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
-            .setLayoutDirection(TOP_TO_BOTTOM)
-            .build()
-        assertEquals(TEST_TAG, rule.tag)
-        assertEquals(NEVER, rule.finishPrimaryWithSecondary)
-        assertEquals(ALWAYS, rule.finishSecondaryWithPrimary)
-        assertEquals(false, rule.clearTop)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertTrue(rule.checkParentBounds(density, validBounds))
-        assertFalse(rule.checkParentBounds(density, invalidBounds))
-    }
-
-    /**
-     * Verifies that default params are set correctly when creating {@link SplitPairRule} with a
-     * builder.
-     */
-    @Test
-    fun testDefaults_SplitPairRule_Builder() {
-        val rule = SplitPairRule.Builder(HashSet()).build()
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
-            .setLayoutDirection(LOCALE)
-            .build()
-        assertNull(rule.tag)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
-        assertEquals(NEVER, rule.finishPrimaryWithSecondary)
-        assertEquals(ALWAYS, rule.finishSecondaryWithPrimary)
-        assertEquals(false, rule.clearTop)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertTrue(rule.checkParentBounds(density, validBounds))
-        assertFalse(rule.checkParentBounds(density, invalidBounds))
-    }
-
-    /**
-     * Verifies that the params are set correctly when creating {@link SplitPairRule} with a
-     * builder.
-     */
-    @Test
-    fun test_SplitPairRule_Builder() {
-        val filters = HashSet<SplitPairFilter>()
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
-            .setLayoutDirection(LEFT_TO_RIGHT)
-            .build()
-        filters.add(
-            SplitPairFilter(
-                ComponentName("a", "b"),
-                ComponentName("c", "d"),
-                "ACTION"
-            )
-        )
-        val rule = SplitPairRule.Builder(filters)
-            .setMinWidthDp(123)
-            .setMinHeightDp(456)
-            .setMinSmallestWidthDp(789)
-            .setMaxAspectRatioInPortrait(ratio(1.23f))
-            .setMaxAspectRatioInLandscape(ratio(4.56f))
-            .setFinishPrimaryWithSecondary(ADJACENT)
-            .setFinishSecondaryWithPrimary(ADJACENT)
-            .setClearTop(true)
-            .setDefaultSplitAttributes(expectedSplitLayout)
-            .setTag(TEST_TAG)
-            .build()
-        assertEquals(ADJACENT, rule.finishPrimaryWithSecondary)
-        assertEquals(ADJACENT, rule.finishSecondaryWithPrimary)
-        assertEquals(true, rule.clearTop)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertEquals(TEST_TAG, rule.tag)
-        assertEquals(filters, rule.filters)
-        assertEquals(123, rule.minWidthDp)
-        assertEquals(456, rule.minHeightDp)
-        assertEquals(789, rule.minSmallestWidthDp)
-        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
-        assertEquals(4.56f, rule.maxAspectRatioInLandscape.value)
-    }
-
-    /**
-     * Verifies that illegal parameter values are not allowed when creating {@link SplitPairRule}
-     * with a builder.
-     */
-    @Test
-    fun test_SplitPairRule_Builder_illegalArguments() {
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMinWidthDp(-1)
-                .setMinHeightDp(456)
-                .setMinSmallestWidthDp(789)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMinWidthDp(123)
-                .setMinHeightDp(-1)
-                .setMinSmallestWidthDp(789)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMinWidthDp(123)
-                .setMinHeightDp(456)
-                .setMinSmallestWidthDp(-1)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMaxAspectRatioInPortrait(ratio(-1f))
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMaxAspectRatioInLandscape(ratio(-1f))
-                .build()
-        }
-    }
-
-    /**
-     * Verifies that the SplitPairRule verifies that the parent bounds satisfy
-     * maxAspectRatioInPortrait.
-     */
-    @Test
-    fun testSplitPairRule_maxAspectRatioInPortrait() {
-        // Always allow split
-        var rule = SplitPairRule.Builder(HashSet())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .build()
-        var width = 100
-        var height = 1000
-        var bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Always disallow split in portrait
-        rule = SplitPairRule.Builder(HashSet())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_DISALLOW)
-            .build()
-        width = 100
-        height = 101
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in landscape
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Compare the aspect ratio in portrait
-        rule = SplitPairRule.Builder(HashSet())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ratio(1.1f))
-            .build()
-        // Equals to the max aspect ratio
-        width = 100
-        height = 110
-        bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-        // Greater than the max aspect ratio
-        width = 100
-        height = 111
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in landscape
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-    }
-
-    /**
-     * Verifies that the SplitPairRule verifies that the parent bounds satisfy
-     * maxAspectRatioInLandscape.
-     */
-    @Test
-    fun testSplitPairRule_maxAspectRatioInLandscape() {
-        // Always allow split
-        var rule = SplitPairRule.Builder(HashSet())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .build()
-        var width = 1000
-        var height = 100
-        var bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Always disallow split in landscape
-        rule = SplitPairRule.Builder(HashSet())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_DISALLOW)
-            .build()
-        width = 101
-        height = 100
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in portrait
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Compare the aspect ratio in landscape
-        rule = SplitPairRule.Builder(HashSet())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ratio(1.1f))
-            .build()
-        // Equals to the max aspect ratio
-        width = 110
-        height = 100
-        bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-        // Greater than the max aspect ratio
-        width = 111
-        height = 100
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in portrait
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-    }
-
-    /**
-     * Verifies that default params are set correctly when reading {@link SplitPlaceholderRule} from
-     * XML.
-     */
-    @Test
-    fun testDefaults_SplitPlaceholderRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_default_split_placeholder_rule)
-        assertEquals(1, rules.size)
-        val rule: SplitPlaceholderRule = rules.first() as SplitPlaceholderRule
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
-            .setLayoutDirection(LOCALE)
-            .build()
-        assertNull(rule.tag)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
-        assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
-        assertEquals(false, rule.isSticky)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertTrue(rule.checkParentBounds(density, validBounds))
-        assertFalse(rule.checkParentBounds(density, invalidBounds))
-    }
-
-    /**
-     * Verifies that params are set correctly when reading {@link SplitPlaceholderRule} from XML.
-     * @see R.xml.test_split_config_custom_split_placeholder_rule for customized value.
-     */
-    @Test
-    fun testCustom_SplitPlaceholderRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_custom_split_placeholder_rule)
-        assertEquals(1, rules.size)
-        val rule: SplitPlaceholderRule = rules.first() as SplitPlaceholderRule
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.1f))
-            .setLayoutDirection(RIGHT_TO_LEFT)
-            .build()
-        assertEquals("rule3", rule.tag)
-        assertEquals(123, rule.minWidthDp)
-        assertEquals(456, rule.minHeightDp)
-        assertEquals(789, rule.minSmallestWidthDp)
-        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
-        assertEquals(ALWAYS_DISALLOW, rule.maxAspectRatioInLandscape)
-        assertEquals(ADJACENT, rule.finishPrimaryWithPlaceholder)
-        assertEquals(true, rule.isSticky)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-    }
-
-    /**
-     * Verifies that horizontal layout are set correctly when reading [SplitPlaceholderRule]
-     * from XML.
-     */
-    @RequiresApi(Build.VERSION_CODES.M)
-    @Test
-    fun testHorizontalLayout_SplitPlaceholderRule_Xml() {
-        assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_split_placeholder_horizontal_layout)
-        assertEquals(1, rules.size)
-        val rule: SplitPlaceholderRule = rules.first() as SplitPlaceholderRule
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
-            .setLayoutDirection(BOTTOM_TO_TOP)
-            .build()
-        assertEquals(TEST_TAG, rule.tag)
-        assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
-        assertEquals(false, rule.isSticky)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertTrue(rule.checkParentBounds(density, validBounds))
-        assertFalse(rule.checkParentBounds(density, invalidBounds))
-    }
-
-    /**
-     * Verifies that default params are set correctly when creating {@link SplitPlaceholderRule}
-     * with a builder.
-     */
-    @Test
-    fun testDefaults_SplitPlaceholderRule_Builder() {
-        val rule = SplitPlaceholderRule.Builder(HashSet(), Intent()).build()
-        assertNull(rule.tag)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
-        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
-        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
-        assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
-        assertEquals(false, rule.isSticky)
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
-            .setLayoutDirection(LOCALE)
-            .build()
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertTrue(rule.checkParentBounds(density, minValidWindowBounds()))
-        assertFalse(rule.checkParentBounds(density, almostValidWindowBounds()))
-    }
-
-    /**
-     * Verifies that the params are set correctly when creating {@link SplitPlaceholderRule} with a
-     * builder.
-     */
-    @Test
-    fun test_SplitPlaceholderRule_Builder() {
-        val filters = HashSet<ActivityFilter>()
-        filters.add(
-            ActivityFilter(
-                ComponentName("a", "b"),
-                "ACTION"
-            )
-        )
-        val intent = Intent("ACTION")
-        val expectedSplitLayout = SplitAttributes.Builder()
-            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
-            .setLayoutDirection(LEFT_TO_RIGHT)
-            .build()
-        val rule = SplitPlaceholderRule.Builder(filters, intent)
-            .setMinWidthDp(123)
-            .setMinHeightDp(456)
-            .setMinSmallestWidthDp(789)
-            .setMaxAspectRatioInPortrait(ratio(1.23f))
-            .setMaxAspectRatioInLandscape(ratio(4.56f))
-            .setFinishPrimaryWithPlaceholder(ADJACENT)
-            .setSticky(true)
-            .setDefaultSplitAttributes(expectedSplitLayout)
-            .setTag(TEST_TAG)
-            .build()
-        assertEquals(ADJACENT, rule.finishPrimaryWithPlaceholder)
-        assertEquals(true, rule.isSticky)
-        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
-        assertEquals(filters, rule.filters)
-        assertEquals(intent, rule.placeholderIntent)
-        assertEquals(123, rule.minWidthDp)
-        assertEquals(456, rule.minHeightDp)
-        assertEquals(789, rule.minSmallestWidthDp)
-        assertEquals(TEST_TAG, rule.tag)
-        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
-        assertEquals(4.56f, rule.maxAspectRatioInLandscape.value)
-    }
-
-    /**
-     * Verifies that illegal parameter values are not allowed when creating
-     * {@link SplitPlaceholderRule} with a builder.
-     */
-    @Test
-    fun test_SplitPlaceholderRule_Builder_illegalArguments() {
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPlaceholderRule.Builder(HashSet(), Intent())
-                .setMinWidthDp(-1)
-                .setMinHeightDp(456)
-                .setMinSmallestWidthDp(789)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPlaceholderRule.Builder(HashSet(), Intent())
-                .setMinWidthDp(123)
-                .setMinHeightDp(-1)
-                .setMinSmallestWidthDp(789)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPlaceholderRule.Builder(HashSet(), Intent())
-                .setMinWidthDp(123)
-                .setMinHeightDp(456)
-                .setMinSmallestWidthDp(-1)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPlaceholderRule.Builder(HashSet(), Intent())
-                .setMinWidthDp(123)
-                .setMinHeightDp(456)
-                .setMinSmallestWidthDp(789)
-                .setFinishPrimaryWithPlaceholder(NEVER)
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMaxAspectRatioInPortrait(ratio(-1f))
-                .build()
-        }
-        assertThrows(IllegalArgumentException::class.java) {
-            SplitPairRule.Builder(HashSet())
-                .setMaxAspectRatioInLandscape(ratio(-1f))
-                .build()
-        }
-    }
-
-    /**
-     * Verifies that the SplitPlaceholderRule verifies that the parent bounds satisfy
-     * maxAspectRatioInPortrait.
-     */
-    @Test
-    fun testSplitPlaceholderRule_maxAspectRatioInPortrait() {
-        // Always allow split
-        var rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .build()
-        var width = 100
-        var height = 1000
-        var bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Always disallow split in portrait
-        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_DISALLOW)
-            .build()
-        width = 100
-        height = 101
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in landscape
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Compare the aspect ratio in portrait
-        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ratio(1.1f))
-            .build()
-        // Equals to the max aspect ratio
-        width = 100
-        height = 110
-        bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-        // Greater than the max aspect ratio
-        width = 100
-        height = 111
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in landscape
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-    }
-
-    /**
-     * Verifies that the SplitPlaceholderRule verifies that the parent bounds satisfy
-     * maxAspectRatioInLandscape.
-     */
-    @Test
-    fun testSplitPlaceholderRule_maxAspectRatioInLandscape() {
-        // Always allow split
-        var rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_ALLOW)
-            .build()
-        var width = 1000
-        var height = 100
-        var bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in portrait
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Always disallow split in landscape
-        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ALWAYS_DISALLOW)
-            .build()
-        width = 101
-        height = 100
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in portrait
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-
-        // Compare the aspect ratio in landscape
-        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
-            .setMinWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinHeightDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMinSmallestWidthDp(SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
-            .setMaxAspectRatioInPortrait(ALWAYS_ALLOW)
-            .setMaxAspectRatioInLandscape(ratio(1.1f))
-            .build()
-        // Equals to the max aspect ratio
-        width = 110
-        height = 100
-        bounds = Rect(0, 0, width, height)
-        assertTrue(rule.checkParentBounds(density, bounds))
-        // Greater than the max aspect ratio
-        width = 111
-        height = 100
-        bounds = Rect(0, 0, width, height)
-        assertFalse(rule.checkParentBounds(density, bounds))
-        // Ignore if the bounds in portrait
-        bounds = Rect(0, 0, height, width)
-        assertTrue(rule.checkParentBounds(density, bounds))
-    }
-
-    /**
-     * Verifies that default params are set correctly when reading {@link ActivityRule} from XML.
-     */
-    @Test
-    fun testDefaults_ActivityRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_default_activity_rule)
-        assertEquals(1, rules.size)
-        val rule: ActivityRule = rules.first() as ActivityRule
-        assertNull(rule.tag)
-        assertFalse(rule.alwaysExpand)
-    }
-
-    /**
-     * Verifies that params are set correctly when reading {@link ActivityRule} from XML.
-     * @see R.xml.test_split_config_custom_activity_rule for customized value.
-     */
-    @Test
-    fun testCustom_ActivityRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_custom_activity_rule)
-        assertEquals(1, rules.size)
-        val rule: ActivityRule = rules.first() as ActivityRule
-        assertEquals("rule1", rule.tag)
-        assertTrue(rule.alwaysExpand)
-    }
-
-    /**
-     * Verifies that [ActivityRule.tag] and [ActivityRule.alwaysExpand] are set correctly when
-     * reading [ActivityRule] from XML.
-     */
-    @Test
-    fun testSetTagAndAlwaysExpand_ActivityRule_Xml() {
-        val rules = RuleController
-            .parseRules(application, R.xml.test_split_config_activity_rule_with_tag)
-        assertEquals(1, rules.size)
-        val rule: ActivityRule = rules.first() as ActivityRule
-        assertEquals(TEST_TAG, rule.tag)
-        assertTrue(rule.alwaysExpand)
-    }
-
-    /**
-     * Verifies that default params are set correctly when creating {@link ActivityRule} with a
-     * builder.
-     */
-    @Test
-    fun testDefaults_ActivityRule_Builder() {
-        val rule = ActivityRule.Builder(HashSet()).build()
-        assertFalse(rule.alwaysExpand)
-    }
-
-    /**
-     * Verifies that the params are set correctly when creating {@link ActivityRule} with a builder.
-     */
-    @Test
-    fun test_ActivityRule_Builder() {
-        val filters = HashSet<ActivityFilter>()
-        filters.add(
-            ActivityFilter(
-                ComponentName("a", "b"),
-                "ACTION"
-            )
-        )
-        val rule = ActivityRule.Builder(filters)
-            .setAlwaysExpand(true)
-            .setTag(TEST_TAG)
-            .build()
-        assertTrue(rule.alwaysExpand)
-        assertEquals(TEST_TAG, rule.tag)
-        assertEquals(filters, rule.filters)
-    }
-
-    private fun minValidWindowBounds(): Rect {
-        // Get the screen's density scale
-        val scale: Float = density
-        // Convert the dps to pixels, based on density scale
-        val minValidWidthPx = (SPLIT_MIN_DIMENSION_DP_DEFAULT * scale + 0.5f).toInt()
-
-        return Rect(0, 0, minValidWidthPx, minValidWidthPx)
-    }
-
-    private fun almostValidWindowBounds(): Rect {
-        // Get the screen's density scale
-        val scale: Float = density
-        // Convert the dps to pixels, based on density scale
-        val minValidWidthPx = ((SPLIT_MIN_DIMENSION_DP_DEFAULT) - 1 * scale + 0.5f).toInt()
-
-        return Rect(0, 0, minValidWidthPx, minValidWidthPx)
-    }
-
-    @Test
-    fun testIllegalTag_XML() {
-        assertThrows(IllegalArgumentException::class.java) {
-            RuleController.parseRules(application, R.xml.test_split_config_duplicated_tag)
-        }
-    }
-
-    @Test
-    fun testReplacingRuleWithTag() {
-        var rules = RuleController
-            .parseRules(application, R.xml.test_split_config_activity_rule_with_tag)
-        assertEquals(1, rules.size)
-        var rule = rules.first()
-        assertEquals(TEST_TAG, rule.tag)
-        val staticRule = rule as ActivityRule
-        assertTrue(staticRule.alwaysExpand)
-        ruleController.setRules(rules)
-
-        val filters = HashSet<ActivityFilter>()
-        filters.add(
-            ActivityFilter(
-                ComponentName("a", "b"),
-                "ACTION"
-            )
-        )
-        val rule1 = ActivityRule.Builder(filters)
-            .setAlwaysExpand(true)
-            .setTag(TEST_TAG)
-            .build()
-        ruleController.addRule(rule1)
-
-        rules = ruleController.getRules()
-        assertEquals(1, rules.size)
-        rule = rules.first()
-        assertEquals(rule1, rule)
-
-        val intent = Intent("ACTION")
-        val rule2 = SplitPlaceholderRule.Builder(filters, intent)
-            .setMinWidthDp(123)
-            .setMinHeightDp(456)
-            .setMinSmallestWidthDp(789)
-            .setTag(TEST_TAG)
-            .build()
-
-        ruleController.addRule(rule2)
-
-        rules = ruleController.getRules()
-        assertEquals(1, rules.size)
-        rule = rules.first()
-        assertEquals(rule2, rule)
-    }
-
-    companion object {
-        const val TEST_TAG = "test"
-    }
-}
\ No newline at end of file
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/RuleParserTests.kt b/window/window/src/androidTest/java/androidx/window/embedding/RuleParserTests.kt
new file mode 100644
index 0000000..2ea8eed
--- /dev/null
+++ b/window/window/src/androidTest/java/androidx/window/embedding/RuleParserTests.kt
@@ -0,0 +1,331 @@
+/*
+ * 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.window.embedding
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.graphics.Rect
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.test.core.app.ApplicationProvider
+import androidx.window.embedding.EmbeddingAspectRatio.Companion.ALWAYS_DISALLOW
+import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.BOTTOM_TO_TOP
+import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.LOCALE
+import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.RIGHT_TO_LEFT
+import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.TOP_TO_BOTTOM
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MIN_DIMENSION_DP_DEFAULT
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.ADJACENT
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.ALWAYS
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.NEVER
+import androidx.window.test.R
+import junit.framework.TestCase.assertNull
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertThrows
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests creation of all embedding rule types and from XML.
+ * @see SplitPairRule
+ * @see SplitRule
+ * @see ActivityRule
+ * @see RuleParser
+ */
+class RuleParserTests {
+    private val application = ApplicationProvider.getApplicationContext<Context>()
+    private val ruleController = RuleController.getInstance(application)
+    private val density = application.resources.displayMetrics.density
+    private lateinit var validBounds: Rect
+    private lateinit var invalidBounds: Rect
+
+    @Before
+    fun setUp() {
+        validBounds = minValidWindowBounds()
+        invalidBounds = almostValidWindowBounds()
+        ruleController.clearRules()
+    }
+
+    /**
+     * Verifies that default params are set correctly when reading {@link SplitPairRule} from XML.
+     */
+    @Test
+    fun testDefaults_SplitPairRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_default_split_pair_rule)
+        assertEquals(1, rules.size)
+        val rule: SplitPairRule = rules.first() as SplitPairRule
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
+            .setLayoutDirection(LOCALE)
+            .build()
+        assertNull(rule.tag)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
+        assertEquals(NEVER, rule.finishPrimaryWithSecondary)
+        assertEquals(ALWAYS, rule.finishSecondaryWithPrimary)
+        assertEquals(false, rule.clearTop)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertTrue(rule.checkParentBounds(density, validBounds))
+        assertFalse(rule.checkParentBounds(density, invalidBounds))
+    }
+
+    /**
+     * Verifies that params are set correctly when reading {@link SplitPairRule} from XML.
+     * @see R.xml.test_split_config_custom_split_pair_rule for customized value.
+     */
+    @Test
+    fun testCustom_SplitPairRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_custom_split_pair_rule)
+        assertEquals(1, rules.size)
+        val rule: SplitPairRule = rules.first() as SplitPairRule
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.1f))
+            .setLayoutDirection(RIGHT_TO_LEFT)
+            .build()
+        assertEquals("rule2", rule.tag)
+        assertEquals(123, rule.minWidthDp)
+        assertEquals(456, rule.minHeightDp)
+        assertEquals(789, rule.minSmallestWidthDp)
+        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
+        assertEquals(ALWAYS_DISALLOW, rule.maxAspectRatioInLandscape)
+        assertEquals(ALWAYS, rule.finishPrimaryWithSecondary)
+        assertEquals(NEVER, rule.finishSecondaryWithPrimary)
+        assertEquals(true, rule.clearTop)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+    }
+
+    /** Verifies that horizontal layout are set correctly when reading [SplitPairRule] from XML. */
+    @Test
+    fun testHorizontalLayout_SplitPairRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_split_pair_rule_horizontal_layout)
+        assertEquals(1, rules.size)
+        val rule: SplitPairRule = rules.first() as SplitPairRule
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
+            .setLayoutDirection(TOP_TO_BOTTOM)
+            .build()
+        assertEquals(TEST_TAG, rule.tag)
+        assertEquals(NEVER, rule.finishPrimaryWithSecondary)
+        assertEquals(ALWAYS, rule.finishSecondaryWithPrimary)
+        assertEquals(false, rule.clearTop)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertTrue(rule.checkParentBounds(density, validBounds))
+        assertFalse(rule.checkParentBounds(density, invalidBounds))
+    }
+
+    /**
+     * Verifies that default params are set correctly when reading {@link SplitPlaceholderRule} from
+     * XML.
+     */
+    @Test
+    fun testDefaults_SplitPlaceholderRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_default_split_placeholder_rule)
+        assertEquals(1, rules.size)
+        val rule: SplitPlaceholderRule = rules.first() as SplitPlaceholderRule
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
+            .setLayoutDirection(LOCALE)
+            .build()
+        assertNull(rule.tag)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
+        assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
+        assertEquals(false, rule.isSticky)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertTrue(rule.checkParentBounds(density, validBounds))
+        assertFalse(rule.checkParentBounds(density, invalidBounds))
+    }
+
+    /**
+     * Verifies that params are set correctly when reading {@link SplitPlaceholderRule} from XML.
+     * @see R.xml.test_split_config_custom_split_placeholder_rule for customized value.
+     */
+    @Test
+    fun testCustom_SplitPlaceholderRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_custom_split_placeholder_rule)
+        assertEquals(1, rules.size)
+        val rule: SplitPlaceholderRule = rules.first() as SplitPlaceholderRule
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.1f))
+            .setLayoutDirection(RIGHT_TO_LEFT)
+            .build()
+        assertEquals("rule3", rule.tag)
+        assertEquals(123, rule.minWidthDp)
+        assertEquals(456, rule.minHeightDp)
+        assertEquals(789, rule.minSmallestWidthDp)
+        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
+        assertEquals(ALWAYS_DISALLOW, rule.maxAspectRatioInLandscape)
+        assertEquals(ADJACENT, rule.finishPrimaryWithPlaceholder)
+        assertEquals(true, rule.isSticky)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+    }
+
+    /**
+     * Verifies that horizontal layout are set correctly when reading [SplitPlaceholderRule]
+     * from XML.
+     */
+    @RequiresApi(Build.VERSION_CODES.M)
+    @Test
+    fun testHorizontalLayout_SplitPlaceholderRule_Xml() {
+        assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_split_placeholder_horizontal_layout)
+        assertEquals(1, rules.size)
+        val rule: SplitPlaceholderRule = rules.first() as SplitPlaceholderRule
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
+            .setLayoutDirection(BOTTOM_TO_TOP)
+            .build()
+        assertEquals(TEST_TAG, rule.tag)
+        assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
+        assertEquals(false, rule.isSticky)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertTrue(rule.checkParentBounds(density, validBounds))
+        assertFalse(rule.checkParentBounds(density, invalidBounds))
+    }
+
+    /**
+     * Verifies that default params are set correctly when reading {@link ActivityRule} from XML.
+     */
+    @Test
+    fun testDefaults_ActivityRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_default_activity_rule)
+        assertEquals(1, rules.size)
+        val rule: ActivityRule = rules.first() as ActivityRule
+        assertNull(rule.tag)
+        assertFalse(rule.alwaysExpand)
+    }
+
+    /**
+     * Verifies that params are set correctly when reading {@link ActivityRule} from XML.
+     * @see R.xml.test_split_config_custom_activity_rule for customized value.
+     */
+    @Test
+    fun testCustom_ActivityRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_custom_activity_rule)
+        assertEquals(1, rules.size)
+        val rule: ActivityRule = rules.first() as ActivityRule
+        assertEquals("rule1", rule.tag)
+        assertTrue(rule.alwaysExpand)
+    }
+
+    /**
+     * Verifies that [ActivityRule.tag] and [ActivityRule.alwaysExpand] are set correctly when
+     * reading [ActivityRule] from XML.
+     */
+    @Test
+    fun testSetTagAndAlwaysExpand_ActivityRule_Xml() {
+        val rules = RuleController
+            .parseRules(application, R.xml.test_split_config_activity_rule_with_tag)
+        assertEquals(1, rules.size)
+        val rule: ActivityRule = rules.first() as ActivityRule
+        assertEquals(TEST_TAG, rule.tag)
+        assertTrue(rule.alwaysExpand)
+    }
+
+    private fun minValidWindowBounds(): Rect {
+        // Get the screen's density scale
+        val scale: Float = density
+        // Convert the dps to pixels, based on density scale
+        val minValidWidthPx = (SPLIT_MIN_DIMENSION_DP_DEFAULT * scale + 0.5f).toInt()
+
+        return Rect(0, 0, minValidWidthPx, minValidWidthPx)
+    }
+
+    private fun almostValidWindowBounds(): Rect {
+        // Get the screen's density scale
+        val scale: Float = density
+        // Convert the dps to pixels, based on density scale
+        val minValidWidthPx = ((SPLIT_MIN_DIMENSION_DP_DEFAULT) - 1 * scale + 0.5f).toInt()
+
+        return Rect(0, 0, minValidWidthPx, minValidWidthPx)
+    }
+
+    @Test
+    fun testIllegalTag_XML() {
+        assertThrows(IllegalArgumentException::class.java) {
+            RuleController.parseRules(application, R.xml.test_split_config_duplicated_tag)
+        }
+    }
+
+    @Test
+    fun testReplacingRuleWithTag() {
+        var rules = RuleController
+            .parseRules(application, R.xml.test_split_config_activity_rule_with_tag)
+        assertEquals(1, rules.size)
+        var rule = rules.first()
+        assertEquals(TEST_TAG, rule.tag)
+        val staticRule = rule as ActivityRule
+        assertTrue(staticRule.alwaysExpand)
+        ruleController.setRules(rules)
+
+        val filters = HashSet<ActivityFilter>()
+        filters.add(
+            ActivityFilter(
+                ComponentName("a", "b"),
+                "ACTION"
+            )
+        )
+        val rule1 = ActivityRule.Builder(filters)
+            .setAlwaysExpand(true)
+            .setTag(TEST_TAG)
+            .build()
+        ruleController.addRule(rule1)
+
+        rules = ruleController.getRules()
+        assertEquals(1, rules.size)
+        rule = rules.first()
+        assertEquals(rule1, rule)
+
+        val intent = Intent("ACTION")
+        val rule2 = SplitPlaceholderRule.Builder(filters, intent)
+            .setMinWidthDp(123)
+            .setMinHeightDp(456)
+            .setMinSmallestWidthDp(789)
+            .setTag(TEST_TAG)
+            .build()
+
+        ruleController.addRule(rule2)
+
+        rules = ruleController.getRules()
+        assertEquals(1, rules.size)
+        rule = rules.first()
+        assertEquals(rule2, rule)
+    }
+
+    companion object {
+        const val TEST_TAG = "test"
+    }
+}
\ No newline at end of file
diff --git a/window/window/src/test/java/androidx/window/embedding/ActivityRuleTest.kt b/window/window/src/test/java/androidx/window/embedding/ActivityRuleTest.kt
index aa266a3..8af21e3 100644
--- a/window/window/src/test/java/androidx/window/embedding/ActivityRuleTest.kt
+++ b/window/window/src/test/java/androidx/window/embedding/ActivityRuleTest.kt
@@ -16,12 +16,16 @@
 
 package androidx.window.embedding
 
+import android.content.ComponentName
 import androidx.window.core.ActivityComponentInfo
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
 
+@RunWith(RobolectricTestRunner::class)
 class ActivityRuleTest {
 
     @Test
@@ -60,7 +64,39 @@
         assertEquals(firstRule.hashCode(), secondRule.hashCode())
     }
 
+    /**
+     * Verifies that default params are set correctly when creating [ActivityRule] with a
+     * builder.
+     */
+    @Test
+    fun testDefaults_ActivityRule_Builder() {
+        val rule = ActivityRule.Builder(HashSet()).build()
+        assertFalse(rule.alwaysExpand)
+    }
+
+    /**
+     * Verifies that the params are set correctly when creating [ActivityRule] with a builder.
+     */
+    @Test
+    fun test_ActivityRule_Builder() {
+        val filters = HashSet<ActivityFilter>()
+        filters.add(
+            ActivityFilter(
+                ComponentName("a", "b"),
+                "ACTION"
+            )
+        )
+        val rule = ActivityRule.Builder(filters)
+            .setAlwaysExpand(true)
+            .setTag(TEST_TAG)
+            .build()
+        assertTrue(rule.alwaysExpand)
+        assertEquals(TEST_TAG, rule.tag)
+        assertEquals(filters, rule.filters)
+    }
+
     companion object {
+        private const val TEST_TAG = "test"
         val FILTER_WITH_ACTIVITY = ActivityFilter(
             ActivityComponentInfo("package", "className"),
             null
diff --git a/window/window/src/test/java/androidx/window/embedding/SplitPairRuleTest.kt b/window/window/src/test/java/androidx/window/embedding/SplitPairRuleTest.kt
index e8b48a2..d02808d 100644
--- a/window/window/src/test/java/androidx/window/embedding/SplitPairRuleTest.kt
+++ b/window/window/src/test/java/androidx/window/embedding/SplitPairRuleTest.kt
@@ -16,10 +16,27 @@
 
 package androidx.window.embedding
 
+import android.content.ComponentName
+import android.graphics.Rect
 import androidx.window.core.ActivityComponentInfo
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MIN_DIMENSION_DP_DEFAULT
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.ALWAYS
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.NEVER
+import junit.framework.TestCase
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertThrows
+import org.junit.Assert.assertTrue
 import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
 
+/**
+ * Unit test for [SplitPairRule] to check the construction is correct by using it's builder.
+ */
+@RunWith(RobolectricTestRunner::class)
 internal class SplitPairRuleTest {
 
     @Test
@@ -43,4 +60,270 @@
             null
         )
     }
+
+    /*------------------------------Class Test------------------------------*/
+    /**
+     * Test hashcode and equals are properly calculated for 2 equal [SplitPairRule]
+     */
+    @Test
+    fun equalsImpliesHashCode() {
+        val filter = SplitPairFilter(
+            ComponentName("a", "b"),
+            ComponentName("c", "d"),
+            "ACTION"
+        )
+        val firstRule = SplitPairRule.Builder(setOf(filter)).build()
+        val secondRule = SplitPairRule.Builder(setOf(filter)).build()
+        assertEquals(firstRule, secondRule)
+        assertEquals(firstRule.hashCode(), secondRule.hashCode())
+    }
+
+    /*------------------------------Builder Test------------------------------*/
+    /**
+     * Verifies that default params are set correctly when creating [SplitPairRule] with a
+     * builder.
+     */
+    @Test
+    fun testDefaults_SplitPairRule_Builder() {
+        val rule = SplitPairRule.Builder(HashSet()).build()
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
+            .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
+            .build()
+        TestCase.assertNull(rule.tag)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
+        assertEquals(NEVER, rule.finishPrimaryWithSecondary)
+        assertEquals(ALWAYS, rule.finishSecondaryWithPrimary)
+        assertEquals(false, rule.clearTop)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertTrue(rule.checkParentBounds(density, validBounds))
+        assertFalse(rule.checkParentBounds(density, invalidBounds))
+    }
+
+    /**
+     * Verifies that the params are set correctly when creating [SplitPairRule] with a
+     * builder.
+     */
+    @Test
+    fun test_SplitPairRule_Builder() {
+        val filters = HashSet<SplitPairFilter>()
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
+            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+            .build()
+        filters.add(
+            SplitPairFilter(
+                ComponentName("a", "b"),
+                ComponentName("c", "d"),
+                "ACTION"
+            )
+        )
+        val rule = SplitPairRule.Builder(filters)
+            .setMinWidthDp(123)
+            .setMinHeightDp(456)
+            .setMinSmallestWidthDp(789)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.23f))
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ratio(4.56f))
+            .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.ADJACENT)
+            .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ADJACENT)
+            .setClearTop(true)
+            .setDefaultSplitAttributes(expectedSplitLayout)
+            .setTag(TEST_TAG)
+            .build()
+        assertEquals(SplitRule.FinishBehavior.ADJACENT, rule.finishPrimaryWithSecondary)
+        assertEquals(SplitRule.FinishBehavior.ADJACENT, rule.finishSecondaryWithPrimary)
+        assertEquals(true, rule.clearTop)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertEquals(TEST_TAG, rule.tag)
+        assertEquals(filters, rule.filters)
+        assertEquals(123, rule.minWidthDp)
+        assertEquals(456, rule.minHeightDp)
+        assertEquals(789, rule.minSmallestWidthDp)
+        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
+        assertEquals(4.56f, rule.maxAspectRatioInLandscape.value)
+    }
+
+    /*------------------------------Functional Test------------------------------*/
+    /**
+     * Verifies that illegal parameter values are not allowed when creating [SplitPairRule]
+     * with a builder.
+     */
+    @Test
+    fun test_SplitPairRule_Builder_illegalArguments() {
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMinWidthDp(-1)
+                .setMinHeightDp(456)
+                .setMinSmallestWidthDp(789)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMinWidthDp(123)
+                .setMinHeightDp(-1)
+                .setMinSmallestWidthDp(789)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMinWidthDp(123)
+                .setMinHeightDp(456)
+                .setMinSmallestWidthDp(-1)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(-1f))
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ratio(-1f))
+                .build()
+        }
+    }
+
+    /**
+     * Verifies that the [SplitPairRule] verifies that the parent bounds satisfy
+     * maxAspectRatioInPortrait.
+     */
+    @Test
+    fun testSplitPairRule_maxAspectRatioInPortrait() {
+        // Always allow split
+        var rule = SplitPairRule.Builder(HashSet())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .build()
+        var width = 100
+        var height = 1000
+        var bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Always disallow split in portrait
+        rule = SplitPairRule.Builder(HashSet())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_DISALLOW)
+            .build()
+        width = 100
+        height = 101
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in landscape
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Compare the aspect ratio in portrait
+        rule = SplitPairRule.Builder(HashSet())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.1f))
+            .build()
+        // Equals to the max aspect ratio
+        width = 100
+        height = 110
+        bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+        // Greater than the max aspect ratio
+        width = 100
+        height = 111
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in landscape
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+    }
+
+    /**
+     * Verifies that the [SplitPairRule] verifies that the parent bounds satisfy
+     * maxAspectRatioInLandscape.
+     */
+    @Test
+    fun testSplitPairRule_maxAspectRatioInLandscape() {
+        // Always allow split
+        var rule = SplitPairRule.Builder(HashSet())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .build()
+        var width = 1000
+        var height = 100
+        var bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Always disallow split in landscape
+        rule = SplitPairRule.Builder(HashSet())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_DISALLOW)
+            .build()
+        width = 101
+        height = 100
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in portrait
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Compare the aspect ratio in landscape
+        rule = SplitPairRule.Builder(HashSet())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ratio(1.1f))
+            .build()
+        // Equals to the max aspect ratio
+        width = 110
+        height = 100
+        bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+        // Greater than the max aspect ratio
+        width = 111
+        height = 100
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in portrait
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+    }
+
+    companion object {
+
+        private const val density = 2f
+        private const val TEST_TAG = "test"
+        private val validBounds: Rect = minValidWindowBounds()
+        private val invalidBounds: Rect = almostValidWindowBounds()
+
+        private fun minValidWindowBounds(): Rect {
+            // Get the screen's density scale
+            val scale: Float = density
+            // Convert the dps to pixels, based on density scale
+            val minValidWidthPx = (SPLIT_MIN_DIMENSION_DP_DEFAULT * scale + 0.5f).toInt()
+            return Rect(0, 0, minValidWidthPx, minValidWidthPx)
+        }
+
+        private fun almostValidWindowBounds(): Rect {
+            // Get the screen's density scale
+            val scale: Float = density
+            // Convert the dps to pixels, based on density scale
+            val minValidWidthPx = ((SPLIT_MIN_DIMENSION_DP_DEFAULT) - 1 * scale + 0.5f).toInt()
+            return Rect(0, 0, minValidWidthPx, minValidWidthPx)
+        }
+    }
 }
\ No newline at end of file
diff --git a/window/window/src/test/java/androidx/window/embedding/SplitPlaceHolderRuleTest.kt b/window/window/src/test/java/androidx/window/embedding/SplitPlaceHolderRuleTest.kt
new file mode 100644
index 0000000..0fa21d3
--- /dev/null
+++ b/window/window/src/test/java/androidx/window/embedding/SplitPlaceHolderRuleTest.kt
@@ -0,0 +1,314 @@
+/*
+ * 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.window.embedding
+
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.Rect
+import androidx.window.core.ActivityComponentInfo
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
+import androidx.window.embedding.SplitRule.Companion.SPLIT_MIN_DIMENSION_DP_DEFAULT
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.ALWAYS
+import androidx.window.embedding.SplitRule.FinishBehavior.Companion.NEVER
+import junit.framework.TestCase
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertThrows
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+/**
+ * Unit test for [SplitPlaceholderRule] to check the construction is correct by using it's builder.
+ */
+@RunWith(RobolectricTestRunner::class)
+internal class SplitPlaceHolderRuleTest {
+
+    /*------------------------------Class Test------------------------------*/
+    /**
+     * Test hashcode and equals are properly calculated for 2 equal [SplitPlaceholderRule]
+     */
+    @Test
+    fun equalsImpliesHashCode() {
+        val filter = ActivityFilter(ActivityComponentInfo("a", "b"), "ACTION")
+        val placeholderIntent = Intent()
+        val firstRule = SplitPlaceholderRule.Builder(setOf(filter), placeholderIntent).build()
+        val secondRule = SplitPlaceholderRule.Builder(setOf(filter), placeholderIntent).build()
+        assertEquals(firstRule, secondRule)
+        assertEquals(firstRule.hashCode(), secondRule.hashCode())
+    }
+
+    /*------------------------------Builder Test------------------------------*/
+    /**
+     * Verifies that default params are set correctly when creating [SplitPlaceholderRule]
+     * with a builder.
+     */
+    @Test
+    fun testDefaults_SplitPlaceholderRule_Builder() {
+        val rule = SplitPlaceholderRule.Builder(HashSet(), Intent()).build()
+        TestCase.assertNull(rule.tag)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minHeightDp)
+        assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minSmallestWidthDp)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT, rule.maxAspectRatioInPortrait)
+        assertEquals(SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT, rule.maxAspectRatioInLandscape)
+        assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
+        assertEquals(false, rule.isSticky)
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.5f))
+            .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
+            .build()
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertTrue(rule.checkParentBounds(density, validBounds))
+        assertFalse(rule.checkParentBounds(density, invalidBounds))
+    }
+
+    /**
+     * Verifies that the params are set correctly when creating [SplitPlaceholderRule] with a
+     * builder.
+     */
+    @Test
+    fun test_SplitPlaceholderRule_Builder() {
+        val filters = HashSet<ActivityFilter>()
+        filters.add(
+            ActivityFilter(
+                ComponentName("a", "b"),
+                "ACTION"
+            )
+        )
+        val intent = Intent("ACTION")
+        val expectedSplitLayout = SplitAttributes.Builder()
+            .setSplitType(SplitAttributes.SplitType.ratio(0.3f))
+            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+            .build()
+        val rule = SplitPlaceholderRule.Builder(filters, intent)
+            .setMinWidthDp(123)
+            .setMinHeightDp(456)
+            .setMinSmallestWidthDp(789)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.23f))
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ratio(4.56f))
+            .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ADJACENT)
+            .setSticky(true)
+            .setDefaultSplitAttributes(expectedSplitLayout)
+            .setTag(TEST_TAG)
+            .build()
+        assertEquals(SplitRule.FinishBehavior.ADJACENT, rule.finishPrimaryWithPlaceholder)
+        assertEquals(true, rule.isSticky)
+        assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
+        assertEquals(filters, rule.filters)
+        assertEquals(intent, rule.placeholderIntent)
+        assertEquals(123, rule.minWidthDp)
+        assertEquals(456, rule.minHeightDp)
+        assertEquals(789, rule.minSmallestWidthDp)
+        assertEquals(TEST_TAG, rule.tag)
+        assertEquals(1.23f, rule.maxAspectRatioInPortrait.value)
+        assertEquals(4.56f, rule.maxAspectRatioInLandscape.value)
+    }
+
+    /**
+     * Verifies that illegal parameter values are not allowed when creating
+     * [SplitPlaceholderRule] with a builder.
+     */
+    @Test
+    fun test_SplitPlaceholderRule_Builder_illegalArguments() {
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPlaceholderRule.Builder(HashSet(), Intent())
+                .setMinWidthDp(-1)
+                .setMinHeightDp(456)
+                .setMinSmallestWidthDp(789)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPlaceholderRule.Builder(HashSet(), Intent())
+                .setMinWidthDp(123)
+                .setMinHeightDp(-1)
+                .setMinSmallestWidthDp(789)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPlaceholderRule.Builder(HashSet(), Intent())
+                .setMinWidthDp(123)
+                .setMinHeightDp(456)
+                .setMinSmallestWidthDp(-1)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPlaceholderRule.Builder(HashSet(), Intent())
+                .setMinWidthDp(123)
+                .setMinHeightDp(456)
+                .setMinSmallestWidthDp(789)
+                .setFinishPrimaryWithPlaceholder(NEVER)
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(-1f))
+                .build()
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            SplitPairRule.Builder(HashSet())
+                .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ratio(-1f))
+                .build()
+        }
+    }
+
+    /*------------------------------Functional Test------------------------------*/
+    /**
+     * Verifies that the [SplitPlaceholderRule] verifies that the parent bounds satisfy
+     * maxAspectRatioInPortrait.
+     */
+    @Test
+    fun testSplitPlaceholderRule_maxAspectRatioInPortrait() {
+        // Always allow split
+        var rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .build()
+        var width = 100
+        var height = 1000
+        var bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Always disallow split in portrait
+        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_DISALLOW)
+            .build()
+        width = 100
+        height = 101
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in landscape
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Compare the aspect ratio in portrait
+        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.1f))
+            .build()
+        // Equals to the max aspect ratio
+        width = 100
+        height = 110
+        bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+        // Greater than the max aspect ratio
+        width = 100
+        height = 111
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in landscape
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+    }
+
+    /**
+     * Verifies that the [SplitPlaceholderRule] verifies that the parent bounds satisfy
+     * maxAspectRatioInLandscape.
+     */
+    @Test
+    fun testSplitPlaceholderRule_maxAspectRatioInLandscape() {
+        // Always allow split
+        var rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .build()
+        var width = 1000
+        var height = 100
+        var bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in portrait
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Always disallow split in landscape
+        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_DISALLOW)
+            .build()
+        width = 101
+        height = 100
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in portrait
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+
+        // Compare the aspect ratio in landscape
+        rule = SplitPlaceholderRule.Builder(HashSet(), Intent())
+            .setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMinSmallestWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
+            .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
+            .setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ratio(1.1f))
+            .build()
+        // Equals to the max aspect ratio
+        width = 110
+        height = 100
+        bounds = Rect(0, 0, width, height)
+        assertTrue(rule.checkParentBounds(density, bounds))
+        // Greater than the max aspect ratio
+        width = 111
+        height = 100
+        bounds = Rect(0, 0, width, height)
+        assertFalse(rule.checkParentBounds(density, bounds))
+        // Ignore if the bounds in portrait
+        bounds = Rect(0, 0, height, width)
+        assertTrue(rule.checkParentBounds(density, bounds))
+    }
+
+    companion object {
+
+        private const val density = 2f
+        private const val TEST_TAG = "test"
+        private val validBounds: Rect = minValidWindowBounds()
+        private val invalidBounds: Rect = almostValidWindowBounds()
+
+        private fun minValidWindowBounds(): Rect {
+            // Get the screen's density scale
+            val scale: Float = density
+            // Convert the dps to pixels, based on density scale
+            val minValidWidthPx = (SPLIT_MIN_DIMENSION_DP_DEFAULT * scale + 0.5f).toInt()
+            return Rect(0, 0, minValidWidthPx, minValidWidthPx)
+        }
+
+        private fun almostValidWindowBounds(): Rect {
+            // Get the screen's density scale
+            val scale: Float = density
+            // Convert the dps to pixels, based on density scale
+            val minValidWidthPx = ((SPLIT_MIN_DIMENSION_DP_DEFAULT) - 1 * scale + 0.5f).toInt()
+            return Rect(0, 0, minValidWidthPx, minValidWidthPx)
+        }
+    }
+}
\ No newline at end of file
diff --git a/work/work-runtime/api/current.ignore b/work/work-runtime/api/current.ignore
index 7b196e5..ecd7f87 100644
--- a/work/work-runtime/api/current.ignore
+++ b/work/work-runtime/api/current.ignore
@@ -1,14 +1,4 @@
 // Baseline format: 1.0
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfoByIdFlow(java.util.UUID):
-    Added method androidx.work.WorkManager.getWorkInfoByIdFlow(java.util.UUID)
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfosByTagFlow(String):
-    Added method androidx.work.WorkManager.getWorkInfosByTagFlow(String)
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfosFlow(androidx.work.WorkQuery):
-    Added method androidx.work.WorkManager.getWorkInfosFlow(androidx.work.WorkQuery)
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfosForUniqueWorkFlow(String):
-    Added method androidx.work.WorkManager.getWorkInfosForUniqueWorkFlow(String)
-
-
 ChangedType: androidx.work.Configuration#getInitializationExceptionHandler():
     Method androidx.work.Configuration.getInitializationExceptionHandler has changed return type from androidx.core.util.Consumer<java.lang.Throwable!> to androidx.core.util.Consumer<java.lang.Throwable>
 ChangedType: androidx.work.Configuration#getSchedulingExceptionHandler():
diff --git a/work/work-runtime/api/restricted_current.ignore b/work/work-runtime/api/restricted_current.ignore
index 7b196e5..ecd7f87 100644
--- a/work/work-runtime/api/restricted_current.ignore
+++ b/work/work-runtime/api/restricted_current.ignore
@@ -1,14 +1,4 @@
 // Baseline format: 1.0
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfoByIdFlow(java.util.UUID):
-    Added method androidx.work.WorkManager.getWorkInfoByIdFlow(java.util.UUID)
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfosByTagFlow(String):
-    Added method androidx.work.WorkManager.getWorkInfosByTagFlow(String)
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfosFlow(androidx.work.WorkQuery):
-    Added method androidx.work.WorkManager.getWorkInfosFlow(androidx.work.WorkQuery)
-AddedAbstractMethod: androidx.work.WorkManager#getWorkInfosForUniqueWorkFlow(String):
-    Added method androidx.work.WorkManager.getWorkInfosForUniqueWorkFlow(String)
-
-
 ChangedType: androidx.work.Configuration#getInitializationExceptionHandler():
     Method androidx.work.Configuration.getInitializationExceptionHandler has changed return type from androidx.core.util.Consumer<java.lang.Throwable!> to androidx.core.util.Consumer<java.lang.Throwable>
 ChangedType: androidx.work.Configuration#getSchedulingExceptionHandler():