Merge "Finalize session when the device is already closed" into androidx-main
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/VirtualFile.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/VirtualFile.kt
index f57ca90..2d5e28c 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/VirtualFile.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/VirtualFile.kt
@@ -164,7 +164,7 @@
 
     override fun executeCommand(block: (String) -> String): String {
         val cmd = block(absolutePath)
-        return trace("UserFile#executeCommand $cmd") {
+        return trace("UserFile#executeCommand $cmd".take(127)) {
             DataInputStream(Runtime.getRuntime().exec(cmd).inputStream)
                 .bufferedReader()
                 .use { it.readText() }
@@ -222,7 +222,7 @@
         var counterOs: CounterOutputStream? = null
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
-            trace("ShellFile#useOutputStream $cmd") {
+            trace("ShellFile#useOutputStream $cmd".take(127)) {
                 val (_, inDescriptor, errDescriptor) = uiAutomation.executeShellCommandRwe(cmd)
                 ParcelFileDescriptor.AutoCloseOutputStream(inDescriptor).use {
                     counterOs = CounterOutputStream(it)
@@ -231,7 +231,7 @@
                 checkErr(errDescriptor)
             }
         } else {
-            trace("ShellFile#useOutputStream $cmd") {
+            trace("ShellFile#useOutputStream $cmd".take(127)) {
                 val (_, inDescriptor) = uiAutomation.executeShellCommandRw(cmd)
                 ParcelFileDescriptor.AutoCloseOutputStream(inDescriptor).use {
                     counterOs = CounterOutputStream(it)
@@ -268,7 +268,7 @@
     override fun executeCommand(block: (String) -> String): String {
         val cmd = rootState.maybeRootify(block(absolutePath))
         val output =
-            trace("ShellFile#executeCommand $cmd") {
+            trace("ShellFile#executeCommand $cmd".take(127)) {
                 uiAutomation.executeShellCommand(cmd).fullyReadInputStream()
             }
         return output.trim()
diff --git a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt
index 7825418..da3cf49 100644
--- a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt
+++ b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt
@@ -16,7 +16,6 @@
 
 package androidx.benchmark.macro.junit4
 
-import android.Manifest
 import androidx.annotation.IntRange
 import androidx.benchmark.Arguments
 import androidx.benchmark.ExperimentalBenchmarkConfigApi
@@ -27,9 +26,7 @@
 import androidx.benchmark.macro.StartupMode
 import androidx.benchmark.macro.macrobenchmarkWithStartupMode
 import androidx.benchmark.perfetto.PerfettoConfig
-import androidx.test.rule.GrantPermissionRule
 import org.junit.Assume.assumeTrue
-import org.junit.rules.RuleChain
 import org.junit.rules.TestRule
 import org.junit.runner.Description
 import org.junit.runners.model.Statement
@@ -226,16 +223,7 @@
             measureBlock
         )
 
-    override fun apply(base: Statement, description: Description): Statement {
-        // Grant external storage, as it may be needed for test output directory.
-        return RuleChain.outerRule(
-                GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
-            )
-            .around(::applyInternal)
-            .apply(base, description)
-    }
-
-    private fun applyInternal(base: Statement, description: Description) =
+    override fun apply(base: Statement, description: Description): Statement =
         object : Statement() {
             override fun evaluate() {
                 assumeTrue(Arguments.RuleType.Macrobenchmark in Arguments.enabledRules)
diff --git a/biometric/biometric/src/main/res/values-fa/strings.xml b/biometric/biometric/src/main/res/values-fa/strings.xml
index 6e9482f..563ced0 100644
--- a/biometric/biometric/src/main/res/values-fa/strings.xml
+++ b/biometric/biometric/src/main/res/values-fa/strings.xml
@@ -23,7 +23,7 @@
     <string name="fingerprint_error_no_fingerprints" msgid="7520712796891883488">"اثر انگشتی ثبت نشده است."</string>
     <string name="fingerprint_error_hw_not_present" msgid="6306988885793029438">"این دستگاه حسگر اثر انگشت ندارد"</string>
     <string name="fingerprint_error_user_canceled" msgid="7627716295344353987">"کاربر عملیات اثر انگشت را لغو کرد"</string>
-    <string name="fingerprint_error_lockout" msgid="7291787166416782245">"تعداد تلاش‌ها بیش از حد مجاز است. لطفاً بعداً دوباره امتحان کنید."</string>
+    <string name="fingerprint_error_lockout" msgid="7291787166416782245">"تلاش‌های بسیار زیاد ناموفق. لطفاً بعداً دوباره امتحان کنید."</string>
     <string name="default_error_msg" msgid="4776854077120974966">"خطای ناشناس"</string>
     <string name="generic_error_user_canceled" msgid="7309881387583143581">"کاربر اصالت‌سنجی را لغو کرد."</string>
     <string name="confirm_device_credential_password" msgid="5912733858573823945">"استفاده از گذرواژه"</string>
diff --git a/buildSrc/lint.xml b/buildSrc/lint.xml
index 78d7c83..98fbf34 100644
--- a/buildSrc/lint.xml
+++ b/buildSrc/lint.xml
@@ -32,6 +32,7 @@
         <ignore path="**/src/androidUnitTest/**" />
         <ignore path="**/src/jvmTest/**" />
         <ignore path="**/src/commonTest/**" />
+        <ignore path="**/src/nonEmulatorJvmTest/**" />
         <!-- Required for AppSearch icing tests. -->
         <ignore path="**/java/tests/**" />
     </issue>
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/sources/ValidateMultiplatformSourceSetNaming.kt b/buildSrc/private/src/main/kotlin/androidx/build/sources/ValidateMultiplatformSourceSetNaming.kt
index 74da1e8..7e117bc 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/sources/ValidateMultiplatformSourceSetNaming.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/sources/ValidateMultiplatformSourceSetNaming.kt
@@ -91,8 +91,8 @@
             project.files(
                 target.compilations
                     .filterNot { compilation ->
-                        // Don't enforce suffixes for test source sets.
-                        compilation.name == "test" || compilation.name.endsWith("Test")
+                        // Don't enforce suffixes for test source sets. Names can be e.g. testOnJvm
+                        compilation.name.startsWith("test") || compilation.name.endsWith("Test")
                     }
                     .flatMap { compilation -> compilation.kotlinSourceSets }
                     .map { kotlinSourceSet -> kotlinSourceSet.kotlin.sourceDirectories }
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 d65cef9..619a198 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
@@ -1140,6 +1140,7 @@
                 closeCameraDeviceOnClose = shouldCloseCameraDeviceOnClose,
                 finalizeSessionOnCloseBehavior = shouldFinalizeSessionOnCloseBehavior,
                 disableGraphLevelSurfaceTracking = shouldDisableGraphLevelSurfaceTracking,
+                enableRestartDelays = true,
             )
         }
     }
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt
index 35386c3..a1d8f5f 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt
@@ -22,7 +22,6 @@
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraStatusMonitor
 import androidx.camera.camera2.pipe.GraphState.GraphStateError
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.StreamId
@@ -172,14 +171,6 @@
         }
     }
 
-    override fun onCameraStatusChanged(cameraStatus: CameraStatusMonitor.CameraStatus) {
-        synchronized(lock) {
-            check(!closed) { "Attempted to invoke restart after close." }
-            stop()
-            start()
-        }
-    }
-
     override fun close() {
         synchronized(lock) {
             closed = true
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
index 56f4beb..f624b2b 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
@@ -24,13 +24,10 @@
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraMetadata
-import androidx.camera.camera2.pipe.CameraStatusMonitor
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.graph.GraphListener
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
 
 /** The FakeCameraBackend implements [CameraBackend] and creates [CameraControllerSimulator]s. */
 public class FakeCameraBackend(private val fakeCameras: Map<CameraId, CameraMetadata>) :
@@ -45,9 +42,6 @@
     override val id: CameraBackendId
         get() = FAKE_CAMERA_BACKEND_ID
 
-    override val cameraStatus: Flow<CameraStatusMonitor.CameraStatus>
-        get() = MutableSharedFlow()
-
     override fun awaitCameraIds(): List<CameraId> = fakeCameraIds
 
     override fun awaitConcurrentCameraIds(): Set<Set<CameraId>> = emptySet()
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
index 2d6dbf6..19859af 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
@@ -18,7 +18,6 @@
 import androidx.annotation.RestrictTo
 import androidx.camera.camera2.pipe.graph.GraphListener
 import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.flow.Flow
 
 /** This is used to uniquely identify a specific backend implementation. */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -26,30 +25,6 @@
 public value class CameraBackendId(public val value: String)
 
 /**
- * A CameraStatusMonitors monitors the status of the cameras, and emits updates when the status of
- * cameras changes, for instance when the camera access priorities have changed or when a particular
- * camera has become available.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public interface CameraStatusMonitor {
-    public val cameraStatus: Flow<CameraStatus>
-
-    public abstract class CameraStatus internal constructor() {
-        public object CameraPrioritiesChanged : CameraStatus() {
-            override fun toString(): String = "CameraPrioritiesChanged"
-        }
-
-        public class CameraAvailable(public val cameraId: CameraId) : CameraStatus() {
-            override fun toString(): String = "CameraAvailable(camera=$cameraId)"
-        }
-
-        public class CameraUnavailable(public val cameraId: CameraId) : CameraStatus() {
-            override fun toString(): String = "CameraUnavailable(camera=$cameraId)"
-        }
-    }
-}
-
-/**
  * A CameraBackend is used by [CameraPipe] to abstract out the lifecycle, state, and interactions
  * with a set of camera devices in a standard way.
  *
@@ -67,12 +42,6 @@
     public val id: CameraBackendId
 
     /**
-     * A flow of camera statuses that provide camera status updates such as when the camera access
-     * priorities have changed, or a certain camera has become available.
-     */
-    public val cameraStatus: Flow<CameraStatusMonitor.CameraStatus>
-
-    /**
      * Read out a list of _openable_ [CameraId]s for this backend. The backend may be able to report
      * Metadata for non-openable cameras. However, these cameras should not appear the list of
      * cameras returned by [getCameraIds].
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt
index 4f39a94..7422678 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt
@@ -64,13 +64,6 @@
     public fun stop()
 
     /**
-     * Restart the current session. This should basically perform stop() then start(). However, the
-     * implementation should handle its internal states correctly, and only restart under the right
-     * [CameraStatusMonitor.CameraStatus] and [ControllerState].
-     */
-    public fun onCameraStatusChanged(cameraStatus: CameraStatusMonitor.CameraStatus)
-
-    /**
      * Close this instance. [start] and [stop] should not be invoked, and any additional calls will
      * be ignored once this method returns. Depending on implementation the underlying camera
      * connection may not be terminated immediately, depending on the [CameraBackend]
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 fd51277..4d05f58 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
@@ -399,7 +399,17 @@
          * - Device(s): LEGACY camera hardware level
          * - API levels: 23 or LEGACY hardware level.
          */
-        val disableGraphLevelSurfaceTracking: Boolean = false
+        val disableGraphLevelSurfaceTracking: Boolean = false,
+
+        /**
+         * Flag to enable CameraGraph to restart its internal camera controller(s) with a delay. The
+         * delay might be needed during Activity switching, to allow time for the preceding Activity
+         * to close its CameraGraphs to allow for the succeeding Activity to acquire the same
+         * camera.
+         * - Bug(s): b/344752133, b/153714651
+         * - Device(s): CameraX users
+         */
+        val enableRestartDelays: Boolean = false
     ) {
 
         @JvmInline
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
index 67a2ed2..b7eb8bb 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
@@ -24,35 +24,27 @@
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraMetadata
-import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.config.Camera2ControllerComponent
 import androidx.camera.camera2.pipe.config.Camera2ControllerConfig
-import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.graph.GraphListener
 import androidx.camera.camera2.pipe.graph.StreamGraphImpl
 import javax.inject.Inject
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.flow.Flow
 
 /** This is the default [CameraBackend] implementation for CameraPipe based on Camera2. */
 internal class Camera2Backend
 @Inject
 constructor(
-    private val threads: Threads,
     private val camera2DeviceCache: Camera2DeviceCache,
     private val camera2MetadataCache: Camera2MetadataCache,
     private val virtualCameraManager: VirtualCameraManager,
     private val camera2CameraControllerComponent: Camera2ControllerComponent.Builder,
-    private val camera2CameraStatusMonitor: Camera2CameraStatusMonitor,
 ) : CameraBackend {
     override val id: CameraBackendId
         get() = CameraBackendId("CXCP-Camera2")
 
-    override val cameraStatus: Flow<CameraStatus>
-        get() = camera2CameraStatusMonitor.cameraStatus
-
     override suspend fun getCameraIds(): List<CameraId> = camera2DeviceCache.getCameraIds()
 
     override fun awaitCameraIds(): List<CameraId>? = camera2DeviceCache.awaitCameraIds()
@@ -111,7 +103,7 @@
                         graphId,
                         graphConfig,
                         graphListener,
-                        streamGraph as StreamGraphImpl
+                        streamGraph as StreamGraphImpl,
                     )
                 )
                 .build()
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 2c7d2ec..fd75f74 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
@@ -25,7 +25,6 @@
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
 import androidx.camera.camera2.pipe.CameraSurfaceManager
 import androidx.camera.camera2.pipe.GraphState
 import androidx.camera.camera2.pipe.StreamGraph
@@ -36,10 +35,13 @@
 import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.core.TimeSource
 import androidx.camera.camera2.pipe.graph.GraphListener
+import androidx.camera.camera2.pipe.internal.CameraStatusMonitor
+import androidx.camera.camera2.pipe.internal.CameraStatusMonitor.CameraStatus
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 
 /**
@@ -59,6 +61,7 @@
     private val threads: Threads,
     private val graphConfig: CameraGraph.Config,
     private val graphListener: GraphListener,
+    private val cameraStatusMonitor: CameraStatusMonitor,
     private val captureSessionFactory: CaptureSessionFactory,
     private val captureSequenceProcessorFactory: Camera2CaptureSequenceProcessorFactory,
     private val virtualCameraManager: VirtualCameraManager,
@@ -84,126 +87,185 @@
 
     @GuardedBy("lock") private var lastCameraError: CameraError? = null
 
+    @GuardedBy("lock") private var restartJob: Job? = null
+
     private var currentCamera: VirtualCamera? = null
     private var currentSession: CaptureSessionState? = null
     private var currentSurfaceMap: Map<StreamId, Surface>? = null
 
     private var currentCameraStateJob: Job? = null
+    private var cameraAvailabilityJob: Job? = null
+    private var cameraPrioritiesJob: Job? = null
 
-    override fun start(): Unit =
-        synchronized(lock) {
-            if (controllerState == ControllerState.CLOSED) {
-                Log.info { "Ignoring start(): Camera2CameraController is already closed" }
-                return
-            } else if (controllerState == ControllerState.STARTED) {
-                Log.warn { "Ignoring start(): Camera2CameraController is already started" }
-                return
-            }
-            lastCameraError = null
-            val camera =
-                virtualCameraManager.open(
-                    graphConfig.camera,
-                    graphConfig.sharedCameraIds,
-                    graphListener,
-                ) { _ ->
-                    isForeground
-                }
-            if (camera == null) {
-                Log.error {
-                    "Failed to start Camera2CameraController: Open request submission failed"
-                }
-                return
-            }
-
-            check(currentCamera == null)
-            check(currentSession == null)
-
-            currentCamera = camera
-            val session =
-                CaptureSessionState(
-                    graphListener,
-                    captureSessionFactory,
-                    captureSequenceProcessorFactory,
-                    cameraSurfaceManager,
-                    timeSource,
-                    graphConfig.flags,
-                    scope
-                )
-            currentSession = session
-
-            val surfaces: Map<StreamId, Surface>? = currentSurfaceMap
-            if (surfaces != null) {
-                session.configureSurfaceMap(surfaces)
-            }
-
-            controllerState = ControllerState.STARTED
-            Log.debug { "Started Camera2CameraController" }
-            currentCameraStateJob?.cancel()
-            currentCameraStateJob = scope.launch { bindSessionToCamera() }
-        }
-
-    override fun stop(): Unit =
-        synchronized(lock) {
-            if (controllerState == ControllerState.CLOSED) {
-                Log.warn { "Ignoring stop(): Camera2CameraController is already closed" }
-                return
-            } else if (
-                controllerState == ControllerState.STOPPING ||
-                    controllerState == ControllerState.STOPPED
-            ) {
-                Log.warn { "Ignoring stop(): CameraController already stopping or stopped" }
-                return
-            }
-
-            val camera = currentCamera
-            val session = currentSession
-
-            currentCamera = null
-            currentSession = null
-
-            controllerState = ControllerState.STOPPING
-            Log.debug { "Stopping Camera2CameraController" }
-            disconnectSessionAndCamera(session, camera)
-        }
-
-    override fun onCameraStatusChanged(cameraStatus: CameraStatus): Unit =
-        synchronized(lock) {
-            Log.debug { "$this ($cameraId) camera status changed to $cameraStatus" }
-            if (
-                cameraStatus is CameraStatus.CameraAvailable ||
-                    cameraStatus is CameraStatus.CameraUnavailable
-            ) {
-                [email protected] = cameraStatus
-            }
-
-            var shouldRestart = false
-            when (controllerState) {
-                ControllerState.DISCONNECTED ->
-                    if (
-                        cameraStatus is CameraStatus.CameraAvailable ||
-                            cameraStatus is CameraStatus.CameraPrioritiesChanged
-                    ) {
-                        shouldRestart = true
+    init {
+        cameraAvailabilityJob =
+            scope.launch {
+                cameraStatusMonitor.cameraAvailability.collect { cameraStatus ->
+                    when (cameraStatus) {
+                        is CameraStatus.CameraAvailable -> {
+                            check(cameraStatus.cameraId == cameraId)
+                            onCameraStatusChanged(cameraStatus)
+                        }
+                        is CameraStatus.CameraUnavailable -> {
+                            check(cameraStatus.cameraId == cameraId)
+                            onCameraStatusChanged(cameraStatus)
+                        }
                     }
-                ControllerState.ERROR ->
-                    if (
-                        cameraStatus is CameraStatus.CameraAvailable &&
-                            lastCameraError != CameraError.ERROR_GRAPH_CONFIG
-                    ) {
-                        shouldRestart = true
-                    }
-            }
-            if (!shouldRestart) {
-                Log.debug {
-                    "Camera status changed but not restarting: " +
-                        "Controller state = $controllerState, camera status = $cameraStatus."
                 }
-                return
             }
-            Log.debug { "Restarting Camera2CameraController" }
-            stop()
-            start()
+
+        cameraPrioritiesJob =
+            scope.launch {
+                cameraStatusMonitor.cameraPriorities.collect {
+                    onCameraStatusChanged(CameraStatus.CameraPrioritiesChanged)
+                }
+            }
+    }
+
+    override fun start() {
+        synchronized(lock) { startLocked() }
+    }
+
+    override fun stop() {
+        synchronized(lock) { stopLocked() }
+    }
+
+    private fun restart(delayMs: Long) {
+        synchronized(lock) {
+            restartJob?.cancel()
+            restartJob =
+                scope.launch {
+                    delay(delayMs)
+                    synchronized(lock) {
+                        if (
+                            controllerState != ControllerState.CLOSED &&
+                                controllerState != ControllerState.STOPPING &&
+                                controllerState != ControllerState.STOPPED
+                        ) {
+                            controllerState
+                            stopLocked()
+                            startLocked()
+                        }
+                    }
+                }
         }
+    }
+
+    @GuardedBy("lock")
+    private fun startLocked() {
+        if (controllerState == ControllerState.CLOSED) {
+            Log.info { "Ignoring start(): Camera2CameraController is already closed" }
+            return
+        } else if (controllerState == ControllerState.STARTED) {
+            Log.warn { "Ignoring start(): Camera2CameraController is already started" }
+            return
+        }
+        lastCameraError = null
+        val camera =
+            virtualCameraManager.open(
+                graphConfig.camera,
+                graphConfig.sharedCameraIds,
+                graphListener,
+            ) { _ ->
+                isForeground
+            }
+        if (camera == null) {
+            Log.error { "Failed to start Camera2CameraController: Open request submission failed" }
+            return
+        }
+
+        check(currentCamera == null)
+        check(currentSession == null)
+
+        currentCamera = camera
+        val session =
+            CaptureSessionState(
+                graphListener,
+                captureSessionFactory,
+                captureSequenceProcessorFactory,
+                cameraSurfaceManager,
+                timeSource,
+                graphConfig.flags,
+                scope
+            )
+        currentSession = session
+
+        val surfaces: Map<StreamId, Surface>? = currentSurfaceMap
+        if (surfaces != null) {
+            session.configureSurfaceMap(surfaces)
+        }
+
+        controllerState = ControllerState.STARTED
+        Log.debug { "Started Camera2CameraController" }
+        currentCameraStateJob?.cancel()
+        currentCameraStateJob = scope.launch { bindSessionToCamera() }
+    }
+
+    @GuardedBy("lock")
+    private fun stopLocked() {
+        if (controllerState == ControllerState.CLOSED) {
+            Log.warn { "Ignoring stop(): Camera2CameraController is already closed" }
+            return
+        } else if (
+            controllerState == ControllerState.STOPPING ||
+                controllerState == ControllerState.STOPPED
+        ) {
+            Log.warn { "Ignoring stop(): CameraController already stopping or stopped" }
+            return
+        }
+
+        val camera = currentCamera
+        val session = currentSession
+
+        currentCamera = null
+        currentSession = null
+
+        controllerState = ControllerState.STOPPING
+        Log.debug { "Stopping Camera2CameraController" }
+        disconnectSessionAndCamera(session, camera)
+    }
+
+    private fun onCameraStatusChanged(cameraStatus: CameraStatus) {
+        val shouldRestart =
+            synchronized(lock) {
+                Log.debug { "$this ($cameraId) camera status changed to $cameraStatus" }
+                if (
+                    cameraStatus is CameraStatus.CameraAvailable ||
+                        cameraStatus is CameraStatus.CameraUnavailable
+                ) {
+                    [email protected] = cameraStatus
+                }
+
+                var shouldRestart = false
+                when (controllerState) {
+                    ControllerState.DISCONNECTED ->
+                        if (
+                            cameraStatus is CameraStatus.CameraAvailable ||
+                                cameraStatus is CameraStatus.CameraPrioritiesChanged
+                        ) {
+                            shouldRestart = true
+                        }
+                    ControllerState.ERROR ->
+                        if (
+                            cameraStatus is CameraStatus.CameraAvailable &&
+                                lastCameraError != CameraError.ERROR_GRAPH_CONFIG
+                        ) {
+                            shouldRestart = true
+                        }
+                }
+                shouldRestart
+            }
+        if (!shouldRestart) {
+            Log.debug {
+                "Camera status changed but not restarting: " +
+                    "Controller state = $controllerState, camera status = $cameraStatus."
+            }
+            return
+        }
+        Log.debug { "Restarting Camera2CameraController" }
+        val delayMs = if (graphConfig.flags.enableRestartDelays) 700L else 0L
+        restart(delayMs)
+    }
 
     override fun close(): Unit =
         synchronized(lock) {
@@ -221,6 +283,11 @@
 
             currentCameraStateJob?.cancel()
             currentCameraStateJob = null
+            cameraAvailabilityJob?.cancel()
+            cameraAvailabilityJob = null
+            cameraPrioritiesJob?.cancel()
+            cameraPrioritiesJob = null
+            cameraStatusMonitor.close()
 
             disconnectSessionAndCamera(session, camera)
             if (graphConfig.flags.closeCameraDeviceOnClose) {
@@ -347,6 +414,8 @@
             }
                 ?: run {
                     Log.warn { "Timeout when disconnecting session and camera for $session" }
+                    Log.info { "Force finalizing current capture session" }
+                    session?.finalizeSession(delayMs = 0)
                     graphListener.onGraphError(
                         GraphState.GraphStateError(
                             CameraError.ERROR_CAMERA_DEVICE,
@@ -358,7 +427,7 @@
     }
 
     companion object {
-        private const val DISCONNECT_TIMEOUT_MS = 3_000L // 3s
+        private const val DISCONNECT_TIMEOUT_MS = 5000L // 5s
         private const val MS_TO_NS = 1_000_000
     }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt
index d49ccd1..2f4c9a3 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt
@@ -19,24 +19,58 @@
 import android.hardware.camera2.CameraManager
 import android.os.Build
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraStatusMonitor
-import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
 import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.camera2.pipe.core.Threads
-import javax.inject.Inject
+import androidx.camera.camera2.pipe.internal.CameraStatusMonitor
+import androidx.camera.camera2.pipe.internal.CameraStatusMonitor.CameraStatus
 import javax.inject.Provider
-import javax.inject.Singleton
+import kotlinx.atomicfu.atomic
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.channels.onFailure
 import kotlinx.coroutines.channels.trySendBlocking
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.launch
 
-@Singleton
-internal class Camera2CameraStatusMonitor
-@Inject
-constructor(cameraManager: Provider<CameraManager>, threads: Threads) : CameraStatusMonitor {
-    override val cameraStatus = callbackFlow {
-        val manager = cameraManager.get()
+internal class Camera2CameraStatusMonitor(
+    cameraManager: Provider<CameraManager>,
+    private val threads: Threads,
+    private val cameraId: CameraId,
+) : CameraStatusMonitor {
+    private val manager = cameraManager.get()
+    private val scope =
+        CoroutineScope(
+            threads.lightweightDispatcher.plus(CoroutineName("CXCP-CameraStatusMonitor"))
+        )
+
+    private val closed = atomic(false)
+
+    private val _cameraAvailability = MutableStateFlow<CameraStatus>(CameraStatus.Unknown)
+    override val cameraAvailability: StateFlow<CameraStatus> = _cameraAvailability.asStateFlow()
+
+    private val _cameraPriorities = MutableSharedFlow<Unit>()
+    override val cameraPriorities: SharedFlow<Unit> = _cameraPriorities.asSharedFlow()
+
+    private val cameraStatus = cameraStatusFlow()
+    private val cameraStatusJob =
+        scope.launch {
+            cameraStatus.collect { cameraStatus ->
+                when (cameraStatus) {
+                    is CameraStatus.CameraAvailable -> _cameraAvailability.emit(cameraStatus)
+                    is CameraStatus.CameraUnavailable -> _cameraAvailability.emit(cameraStatus)
+                    is CameraStatus.CameraPrioritiesChanged -> _cameraPriorities.emit(Unit)
+                }
+            }
+        }
+
+    private fun cameraStatusFlow() = callbackFlow {
         val availabilityCallback =
             object : CameraManager.AvailabilityCallback() {
                 override fun onCameraAccessPrioritiesChanged() {
@@ -47,12 +81,14 @@
                 }
 
                 override fun onCameraAvailable(cameraId: String) {
+                    if (cameraId != [email protected]) return
                     Log.debug { "Camera $cameraId has become available" }
                     trySendBlocking(CameraStatus.CameraAvailable(CameraId.fromCamera2Id(cameraId)))
                         .onFailure { Log.warn { "Failed to emit CameraAvailable($cameraId)" } }
                 }
 
                 override fun onCameraUnavailable(cameraId: String) {
+                    if (cameraId != [email protected]) return
                     Log.debug { "Camera $cameraId has become unavailable" }
                     trySendBlocking(
                             CameraStatus.CameraUnavailable(CameraId.fromCamera2Id(cameraId))
@@ -72,4 +108,10 @@
 
         awaitClose { manager.unregisterAvailabilityCallback(availabilityCallback) }
     }
+
+    override fun close() {
+        if (closed.compareAndSet(expect = false, update = true)) {
+            cameraStatusJob.cancel()
+        }
+    }
 }
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 8a69c5d..99a6f15 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
@@ -367,7 +367,7 @@
         }
     }
 
-    private fun finalizeSession(delayMs: Long = 0L) {
+    internal fun finalizeSession(delayMs: Long = 0L) {
         if (delayMs != 0L) {
             scope.launch {
                 Log.debug { "Finalizing $this in $delayMs ms" }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt
index 818ace31..a329318 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt
@@ -24,7 +24,6 @@
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraStatusMonitor
 import androidx.camera.camera2.pipe.CaptureSequence
 import androidx.camera.camera2.pipe.CaptureSequenceProcessor
 import androidx.camera.camera2.pipe.Metadata
@@ -73,11 +72,6 @@
         }
     }
 
-    override fun onCameraStatusChanged(cameraStatus: CameraStatusMonitor.CameraStatus) {
-        // This is intentionally made a no-op for now as CameraPipe external doesn't support
-        // camera status monitoring and camera controller restart.
-    }
-
     override fun close() {
         // TODO: ExternalRequestProcessor will be deprecated. This is a temporary patch to allow
         //   graphProcessor to have a suspending shutdown function.
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
index 589e929..7f403c5 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
@@ -16,11 +16,11 @@
 
 package androidx.camera.camera2.pipe.config
 
+import android.hardware.camera2.CameraManager
 import androidx.camera.camera2.pipe.CameraBackend
 import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraphId
-import androidx.camera.camera2.pipe.CameraStatusMonitor
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.compat.AudioRestrictionController
 import androidx.camera.camera2.pipe.compat.AudioRestrictionControllerImpl
@@ -43,10 +43,12 @@
 import androidx.camera.camera2.pipe.graph.GraphListener
 import androidx.camera.camera2.pipe.graph.StreamGraphImpl
 import androidx.camera.camera2.pipe.internal.CameraErrorListener
+import androidx.camera.camera2.pipe.internal.CameraStatusMonitor
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import dagger.Subcomponent
+import javax.inject.Provider
 import javax.inject.Scope
 import kotlinx.coroutines.CoroutineName
 import kotlinx.coroutines.CoroutineScope
@@ -75,11 +77,6 @@
     ): CameraAvailabilityMonitor
 
     @Binds
-    abstract fun bindCameraStatusMonitor(
-        camera2CameraStatusMonitor: Camera2CameraStatusMonitor
-    ): CameraStatusMonitor
-
-    @Binds
     abstract fun bindCamera2DeviceCloser(
         camera2CameraDeviceCloser: Camera2DeviceCloserImpl
     ): Camera2DeviceCloser
@@ -151,5 +148,15 @@
                 threads.lightweightDispatcher.plus(CoroutineName("CXCP-Camera2Controller"))
             )
         }
+
+        @Camera2ControllerScope
+        @Provides
+        fun provideCameraStatusMonitor(
+            cameraManager: Provider<CameraManager>,
+            threads: Threads,
+            graphConfig: CameraGraph.Config
+        ): CameraStatusMonitor {
+            return Camera2CameraStatusMonitor(cameraManager, threads, graphConfig.camera)
+        }
     }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
index e337f8e..e0d3b49 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
@@ -54,8 +54,6 @@
 /** Qualifier for requesting the CameraPipe scoped Context object */
 @Qualifier internal annotation class CameraPipeContext
 
-@Qualifier internal annotation class ForGraphLifecycleManager
-
 @Singleton
 @Component(
     modules =
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
index 4035977..7089a3b 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
@@ -26,7 +26,6 @@
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraMetadata
-import androidx.camera.camera2.pipe.CameraStatusMonitor
 import androidx.camera.camera2.pipe.RequestProcessor
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.compat.ExternalCameraController
@@ -35,8 +34,6 @@
 import dagger.Provides
 import dagger.Subcomponent
 import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
 
 @CameraGraphScope
 @Subcomponent(modules = [SharedCameraGraphModules::class, ExternalCameraGraphConfigModule::class])
@@ -62,9 +59,6 @@
             override val id: CameraBackendId
                 get() = CameraBackendId("External")
 
-            override val cameraStatus: Flow<CameraStatusMonitor.CameraStatus>
-                get() = MutableSharedFlow()
-
             override suspend fun getCameraIds(): List<CameraId>? {
                 throwUnsupportedOperationException()
             }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ThreadConfigModule.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ThreadConfigModule.kt
index 1e3d6cf..ec923aa 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ThreadConfigModule.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ThreadConfigModule.kt
@@ -43,7 +43,7 @@
     // Lightweight executors are for CPU bound work that should take less than ~10ms to operate and
     // do not block the calling thread.
     private val lightweightThreadCount: Int =
-        maxOf(2, Runtime.getRuntime().availableProcessors() - 2)
+        maxOf(4, Runtime.getRuntime().availableProcessors() - 2)
 
     // Background thread count is for operations that are not latency sensitive and may take more
     // than a few milliseconds to run.
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
index ad0de5a..e7ee3477 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
@@ -19,7 +19,6 @@
 import android.os.Build
 import android.view.Surface
 import androidx.camera.camera2.pipe.AudioRestrictionMode
-import androidx.camera.camera2.pipe.CameraBackend
 import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraGraphId
@@ -37,7 +36,6 @@
 import androidx.camera.camera2.pipe.core.tryAcquireToken
 import androidx.camera.camera2.pipe.internal.FrameCaptureQueue
 import androidx.camera.camera2.pipe.internal.FrameDistributor
-import androidx.camera.camera2.pipe.internal.GraphLifecycleManager
 import javax.inject.Inject
 import kotlinx.atomicfu.atomic
 import kotlinx.coroutines.CoroutineScope
@@ -56,12 +54,10 @@
 constructor(
     graphConfig: CameraGraph.Config,
     metadata: CameraMetadata,
-    private val graphLifecycleManager: GraphLifecycleManager,
     private val graphProcessor: GraphProcessor,
     private val graphListener: GraphListener,
     private val streamGraph: StreamGraphImpl,
     private val surfaceGraph: SurfaceGraph,
-    private val cameraBackend: CameraBackend,
     private val cameraController: CameraController,
     private val graphState3A: GraphState3A,
     private val listener3A: Listener3A,
@@ -135,7 +131,7 @@
         Debug.traceStart { "$this#start" }
         Log.info { "Starting $this" }
         graphListener.onGraphStarting()
-        graphLifecycleManager.monitorAndStart(cameraBackend, cameraController)
+        cameraController.start()
         Debug.traceStop()
     }
 
@@ -145,7 +141,7 @@
         Debug.traceStart { "$this#stop" }
         Log.info { "Stopping $this" }
         graphListener.onGraphStopping()
-        graphLifecycleManager.monitorAndStop(cameraBackend, cameraController)
+        cameraController.stop()
         Debug.traceStop()
     }
 
@@ -211,7 +207,7 @@
             Debug.traceStart { "$this#close" }
             Log.info { "Closing $this" }
             graphProcessor.close()
-            graphLifecycleManager.monitorAndClose(cameraBackend, cameraController)
+            cameraController.close()
             frameDistributor.close()
             frameCaptureQueue.close()
             surfaceGraph.close()
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraStatusMonitor.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraStatusMonitor.kt
new file mode 100644
index 0000000..869f506
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraStatusMonitor.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 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.internal
+
+import androidx.annotation.RestrictTo
+import androidx.camera.camera2.pipe.CameraId
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.StateFlow
+
+/**
+ * A CameraStatusMonitor monitors the status of the cameras, and emits updates when the status of
+ * cameras changes, for instance when the camera access priorities have changed or when a particular
+ * camera has become available.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+internal interface CameraStatusMonitor : AutoCloseable {
+
+    /** Gets the state flow of the availability of the current camera. */
+    val cameraAvailability: StateFlow<CameraStatus>
+
+    /** A shared flow that emits when camera access priorities have changed. */
+    val cameraPriorities: SharedFlow<Unit>
+
+    abstract class CameraStatus internal constructor() {
+        object Unknown : CameraStatus() {
+            override fun toString(): String = "UnknownCameraStatus"
+        }
+
+        object CameraPrioritiesChanged : CameraStatus() {
+            override fun toString(): String = "CameraPrioritiesChanged"
+        }
+
+        class CameraAvailable(val cameraId: CameraId) : CameraStatus() {
+            override fun toString(): String = "CameraAvailable(camera=$cameraId)"
+        }
+
+        class CameraUnavailable(val cameraId: CameraId) : CameraStatus() {
+            override fun toString(): String = "CameraUnavailable(camera=$cameraId)"
+        }
+    }
+}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/GraphLifecycleManager.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/GraphLifecycleManager.kt
deleted file mode 100644
index f56d3aa..0000000
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/GraphLifecycleManager.kt
+++ /dev/null
@@ -1,153 +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.camera2.pipe.internal
-
-import androidx.annotation.GuardedBy
-import androidx.camera.camera2.pipe.CameraBackend
-import androidx.camera.camera2.pipe.CameraBackendId
-import androidx.camera.camera2.pipe.CameraController
-import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraStatusMonitor
-import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
-import androidx.camera.camera2.pipe.core.Threads
-import javax.inject.Inject
-import javax.inject.Singleton
-import kotlinx.coroutines.CoroutineName
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.launch
-
-/**
- * GraphLifecycleManager is a CameraPipe-level lifecycle manager that does the following:
- * - Oversees and executes the operations of [CameraController]`s. This means it will make sure the
- *   operations are atomic, and executed based on permissible state transitions.
- * - Subscribe to [CameraStatusMonitor]s for camera status changes, basically “can attempt to
- *   restart signals”, from the respective camera backends, and then only restart
- *   [CameraController]s when the conditions are right.
- * - Once we've determined that we can restart [CameraController]s, select the “suitable”
- *   [CameraController] to restart.
- */
-@Singleton
-internal class GraphLifecycleManager @Inject constructor(val threads: Threads) {
-    private val lock = Any()
-
-    private val scope =
-        CoroutineScope(
-            threads.lightweightDispatcher.plus(CoroutineName("CXCP-GraphLifecycleManager"))
-        )
-
-    @GuardedBy("lock")
-    private val backendControllerMap =
-        mutableMapOf<CameraBackendId, LinkedHashSet<CameraController>>()
-
-    @GuardedBy("lock")
-    private val backendCameraStatusMap =
-        mutableMapOf<CameraBackendId, MutableMap<CameraId, CameraStatus>>()
-
-    @GuardedBy("lock") private val backendStatusCollectJobMap = mutableMapOf<CameraBackendId, Job>()
-
-    internal fun monitorAndStart(cameraBackend: CameraBackend, cameraController: CameraController) =
-        synchronized(lock) {
-            startMonitoring(cameraBackend, cameraController)
-            cameraController.start()
-        }
-
-    internal fun monitorAndStop(cameraBackend: CameraBackend, cameraController: CameraController) =
-        synchronized(lock) {
-            cameraController.stop()
-            stopMonitoring(cameraBackend, cameraController)
-        }
-
-    internal fun monitorAndClose(cameraBackend: CameraBackend, cameraController: CameraController) =
-        synchronized(lock) {
-            cameraController.close()
-            stopMonitoring(cameraBackend, cameraController)
-        }
-
-    @GuardedBy("lock")
-    private fun startMonitoring(cameraBackend: CameraBackend, cameraController: CameraController) {
-        // Update this camera controller with the latest camera status, if exist.
-        backendCameraStatusMap[cameraBackend.id]?.get(cameraController.cameraId)?.let { status ->
-            cameraController.onCameraStatusChanged(status)
-        }
-
-        if (backendControllerMap.containsKey(cameraBackend.id)) {
-            backendControllerMap[cameraBackend.id]?.add(cameraController)
-            return
-        }
-        backendControllerMap[cameraBackend.id] = linkedSetOf(cameraController)
-        backendStatusCollectJobMap[cameraBackend.id] =
-            scope.launch {
-                cameraBackend.cameraStatus.collect { cameraStatus ->
-                    when (cameraStatus) {
-                        is CameraStatus.CameraPrioritiesChanged ->
-                            onCameraStatusChanged(cameraBackend, cameraStatus)
-                        is CameraStatus.CameraAvailable ->
-                            onCameraStatusChanged(
-                                cameraBackend,
-                                cameraStatus,
-                                cameraStatus.cameraId,
-                            )
-                        is CameraStatus.CameraUnavailable ->
-                            onCameraStatusChanged(
-                                cameraBackend,
-                                cameraStatus,
-                                cameraStatus.cameraId,
-                            )
-                    }
-                }
-            }
-    }
-
-    @GuardedBy("lock")
-    private fun stopMonitoring(cameraBackend: CameraBackend, cameraController: CameraController) {
-        if (backendControllerMap.containsKey(cameraBackend.id)) {
-            val controllerSet = backendControllerMap[cameraBackend.id]
-            controllerSet?.remove(cameraController)
-            if (controllerSet?.size == 0) {
-                backendControllerMap.remove(cameraBackend.id)
-                backendStatusCollectJobMap[cameraBackend.id]?.cancel()
-                backendStatusCollectJobMap.remove(cameraBackend.id)
-            }
-        }
-    }
-
-    private fun onCameraStatusChanged(
-        cameraBackend: CameraBackend,
-        cameraStatus: CameraStatus,
-        cameraId: CameraId? = null,
-    ) =
-        synchronized(lock) {
-            if (cameraId != null) {
-                val cameraStatusMap =
-                    backendCameraStatusMap.getOrPut(cameraBackend.id) { mutableMapOf() }
-                cameraStatusMap[cameraId] = cameraStatus
-            }
-            // Restart the last CameraController being tracked in each backend. The last
-            // CameraController would be the latest one being tracked, and should thus take priority
-            // over previous CameraControllers.
-            backendControllerMap[cameraBackend.id]
-                ?.findLast {
-                    if (cameraId != null) {
-                        it.cameraId == cameraId
-                    } else {
-                        true
-                    }
-                }
-                ?.onCameraStatusChanged(cameraStatus)
-        }
-}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
index fb91e7d..8fd32cc 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
@@ -34,7 +34,6 @@
 import androidx.camera.camera2.pipe.internal.CameraGraphParametersImpl
 import androidx.camera.camera2.pipe.internal.FrameCaptureQueue
 import androidx.camera.camera2.pipe.internal.FrameDistributor
-import androidx.camera.camera2.pipe.internal.GraphLifecycleManager
 import androidx.camera.camera2.pipe.internal.ImageSourceMap
 import androidx.camera.camera2.pipe.media.ImageReaderImageSources
 import androidx.camera.camera2.pipe.testing.CameraControllerSimulator
@@ -109,7 +108,6 @@
             threads
         )
     private val cameraContext = CameraBackendsImpl.CameraBackendContext(context, threads, backends)
-    private val graphLifecycleManager = GraphLifecycleManager(threads)
     private val imageSources = ImageReaderImageSources(threads)
     private val frameCaptureQueue = FrameCaptureQueue()
     private val cameraController =
@@ -134,12 +132,10 @@
         CameraGraphImpl(
             graphConfig,
             metadata,
-            graphLifecycleManager,
             fakeGraphProcessor,
             fakeGraphProcessor,
             streamGraph,
             surfaceGraph,
-            backend,
             cameraController,
             GraphState3A(),
             Listener3A(),
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
index 1319fc0..f3a3e4a 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
@@ -20,7 +20,6 @@
 import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraphId
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraStatusMonitor
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.StreamId
 
@@ -41,11 +40,6 @@
         started = false
     }
 
-    override fun onCameraStatusChanged(cameraStatus: CameraStatusMonitor.CameraStatus) {
-        stop()
-        start()
-    }
-
     override fun close() {
         closed = true
         started = false
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraControl.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraControl.java
index 947f25b..19bb708 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraControl.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraControl.java
@@ -15,6 +15,7 @@
  */
 package androidx.camera.core.streamsharing;
 
+import static androidx.camera.core.ImageCapture.FLASH_TYPE_USE_TORCH_AS_FLASH;
 import static androidx.core.util.Preconditions.checkArgument;
 
 import static java.util.Collections.singletonList;
@@ -58,8 +59,14 @@
             @ImageCapture.FlashType int flashType) {
         checkArgument(captureConfigs.size() == 1, "Only support one capture config.");
 
+        // FLASH_TYPE_USE_TORCH_AS_FLASH is used to ensure the flash is always on when capturing.
+        // Since we are using JPEG snapshot here, there is no way for the framework to know exactly
+        // when capture is invoked and thus torch as flash workaround is required. Note that this
+        // becomes an issue only when TEMPLATE_PREVIEW is used, usually due to quirk like
+        // PreviewUnderExposureQuirk right now, since TEMPLATE_RECORD would use torch as flash
+        // capture workaround anyway.
         ListenableFuture<CameraCapturePipeline> capturePipeline = getCameraCapturePipelineAsync(
-                captureMode, flashType);
+                captureMode, FLASH_TYPE_USE_TORCH_AS_FLASH);
 
         ListenableFuture<Void> captureFuture = FutureChain.from(
                 capturePipeline
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 ed807fd..7acbea7 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
@@ -793,7 +793,8 @@
     @Test
     fun updateVideoUsage_whenRecordingStartedPausedResumedStopped(): Unit = runBlocking {
         implName.ignoreTestForCameraPipe(
-            "TODO: b/339615736 - Enable when implemented at camera-pipe"
+            "TODO: b/339615736 - Enable when implemented at camera-pipe",
+            evenInLab = true,
         )
 
         checkAndBindUseCases(videoCapture, preview)
@@ -832,7 +833,8 @@
             assumeStopCodecAfterSurfaceRemovalCrashMediaServerQuirk()
 
             implName.ignoreTestForCameraPipe(
-                "TODO: b/339615736 - Enable when implemented at camera-pipe"
+                "TODO: b/339615736 - Enable when implemented at camera-pipe",
+                evenInLab = true,
             )
 
             checkAndBindUseCases(preview, videoCapture)
@@ -864,7 +866,8 @@
         assumeStopCodecAfterSurfaceRemovalCrashMediaServerQuirk()
 
         implName.ignoreTestForCameraPipe(
-            "TODO: b/339615736 - Enable when implemented at camera-pipe"
+            "TODO: b/339615736 - Enable when implemented at camera-pipe",
+            evenInLab = true,
         )
 
         checkAndBindUseCases(preview, videoCapture)
@@ -888,7 +891,8 @@
         )
 
         implName.ignoreTestForCameraPipe(
-            "TODO: b/339615736 - Enable when implemented at camera-pipe"
+            "TODO: b/339615736 - Enable when implemented at camera-pipe",
+            evenInLab = true,
         )
 
         checkAndBindUseCases(preview, videoCapture)
@@ -922,7 +926,8 @@
         )
 
         implName.ignoreTestForCameraPipe(
-            "TODO: b/339615736 - Enable when implemented at camera-pipe"
+            "TODO: b/339615736 - Enable when implemented at camera-pipe",
+            evenInLab = true,
         )
 
         checkAndBindUseCases(preview, videoCapture)
@@ -956,7 +961,8 @@
         )
 
         implName.ignoreTestForCameraPipe(
-            "TODO: b/339615736 - Enable when implemented at camera-pipe"
+            "TODO: b/339615736 - Enable when implemented at camera-pipe",
+            evenInLab = true,
         )
 
         checkAndBindUseCases(preview, videoCapture)
diff --git a/camera/camera-view/api/current.txt b/camera/camera-view/api/current.txt
index 3b66417..d2fd422 100644
--- a/camera/camera-view/api/current.txt
+++ b/camera/camera-view/api/current.txt
@@ -85,9 +85,6 @@
     field @Deprecated public static final int UNASSIGNED_ASPECT_RATIO = -1; // 0xffffffff
   }
 
-  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalPreviewViewScreenFlash {
-  }
-
   public final class LifecycleCameraController extends androidx.camera.view.CameraController {
     ctor public LifecycleCameraController(android.content.Context);
     method @MainThread public void bindToLifecycle(androidx.lifecycle.LifecycleOwner);
@@ -106,7 +103,7 @@
     method @SuppressCompatibility public androidx.camera.view.transform.OutputTransform? getOutputTransform();
     method public androidx.lifecycle.LiveData<androidx.camera.view.PreviewView.StreamState!> getPreviewStreamState();
     method @UiThread public androidx.camera.view.PreviewView.ScaleType getScaleType();
-    method @SuppressCompatibility @UiThread @androidx.camera.view.ExperimentalPreviewViewScreenFlash public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method @UiThread public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
     method @UiThread public android.graphics.Matrix? getSensorToViewTransform();
     method @UiThread public androidx.camera.core.Preview.SurfaceProvider getSurfaceProvider();
     method @UiThread public androidx.camera.core.ViewPort? getViewPort();
@@ -114,7 +111,7 @@
     method @UiThread public void setController(androidx.camera.view.CameraController?);
     method @UiThread public void setImplementationMode(androidx.camera.view.PreviewView.ImplementationMode);
     method @UiThread public void setScaleType(androidx.camera.view.PreviewView.ScaleType);
-    method @SuppressCompatibility @androidx.camera.view.ExperimentalPreviewViewScreenFlash public void setScreenFlashOverlayColor(@ColorInt int);
+    method public void setScreenFlashOverlayColor(@ColorInt int);
     method @UiThread public void setScreenFlashWindow(android.view.Window?);
   }
 
diff --git a/camera/camera-view/api/restricted_current.txt b/camera/camera-view/api/restricted_current.txt
index 3b66417..d2fd422 100644
--- a/camera/camera-view/api/restricted_current.txt
+++ b/camera/camera-view/api/restricted_current.txt
@@ -85,9 +85,6 @@
     field @Deprecated public static final int UNASSIGNED_ASPECT_RATIO = -1; // 0xffffffff
   }
 
-  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalPreviewViewScreenFlash {
-  }
-
   public final class LifecycleCameraController extends androidx.camera.view.CameraController {
     ctor public LifecycleCameraController(android.content.Context);
     method @MainThread public void bindToLifecycle(androidx.lifecycle.LifecycleOwner);
@@ -106,7 +103,7 @@
     method @SuppressCompatibility public androidx.camera.view.transform.OutputTransform? getOutputTransform();
     method public androidx.lifecycle.LiveData<androidx.camera.view.PreviewView.StreamState!> getPreviewStreamState();
     method @UiThread public androidx.camera.view.PreviewView.ScaleType getScaleType();
-    method @SuppressCompatibility @UiThread @androidx.camera.view.ExperimentalPreviewViewScreenFlash public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method @UiThread public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
     method @UiThread public android.graphics.Matrix? getSensorToViewTransform();
     method @UiThread public androidx.camera.core.Preview.SurfaceProvider getSurfaceProvider();
     method @UiThread public androidx.camera.core.ViewPort? getViewPort();
@@ -114,7 +111,7 @@
     method @UiThread public void setController(androidx.camera.view.CameraController?);
     method @UiThread public void setImplementationMode(androidx.camera.view.PreviewView.ImplementationMode);
     method @UiThread public void setScaleType(androidx.camera.view.PreviewView.ScaleType);
-    method @SuppressCompatibility @androidx.camera.view.ExperimentalPreviewViewScreenFlash public void setScreenFlashOverlayColor(@ColorInt int);
+    method public void setScreenFlashOverlayColor(@ColorInt int);
     method @UiThread public void setScreenFlashWindow(android.view.Window?);
   }
 
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/ExperimentalPreviewViewScreenFlash.java b/camera/camera-view/src/main/java/androidx/camera/view/ExperimentalPreviewViewScreenFlash.java
deleted file mode 100644
index df9117e..0000000
--- a/camera/camera-view/src/main/java/androidx/camera/view/ExperimentalPreviewViewScreenFlash.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2024 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.view;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import androidx.annotation.RequiresOptIn;
-
-import java.lang.annotation.Retention;
-
-/**
- * Denotes that the annotated API is designed to be experimental for the screen flash feature and
- * may change in a future release.
- */
-@Retention(CLASS)
-@RequiresOptIn
-public @interface ExperimentalPreviewViewScreenFlash {
-}
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index d128e54..5af22bf 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -1179,7 +1179,6 @@
      * @see ScreenFlashView#getScreenFlash()
      * @see ImageCapture#FLASH_MODE_SCREEN
      */
-    @ExperimentalPreviewViewScreenFlash
     @UiThread
     @Nullable
     public ImageCapture.ScreenFlash getScreenFlash() {
@@ -1194,7 +1193,6 @@
      * @see #getScreenFlash()
      * @see ImageCapture#FLASH_MODE_SCREEN
      */
-    @ExperimentalPreviewViewScreenFlash
     public void setScreenFlashOverlayColor(@ColorInt int color) {
         mScreenFlashView.setBackgroundColor(color);
     }
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt
index ece3c3d..75727d7 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt
@@ -137,7 +137,7 @@
         var cameras = currentCameras
         cameras?.let {
             for (camera in it) {
-                camera.stop()
+                camera.close()
             }
         }
         Trace.endSection()
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FlashTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FlashTest.kt
index 527aeae..2e8fc9a 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FlashTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/FlashTest.kt
@@ -209,13 +209,16 @@
     fun flashEnabledInRequest_whenCapturedWithFlashOnAndSharedEffect() {
         verifyRequestAeOrFlashModeForFlashModeCapture(
             ImageCapture.FLASH_MODE_ON,
-            addSharedEffect = true
+            addSharedEffect = true,
+            // In this test, torch as flash workaround should always be used
+            expectedAeMode = CONTROL_AE_MODE_ON,
         )
     }
 
     private fun verifyRequestAeOrFlashModeForFlashModeCapture(
         @ImageCapture.FlashMode flashMode: Int,
         addSharedEffect: Boolean = false,
+        expectedAeMode: Int? = null,
     ) {
         Assume.assumeFalse(
             "Cuttlefish API 29 has AE mode availability issue for flash enabled modes." +
@@ -234,11 +237,12 @@
                 @Volatile var isAeModeExpected = true
 
                 private val expectedAeMode =
-                    when (flashMode) {
-                        ImageCapture.FLASH_MODE_ON -> CONTROL_AE_MODE_ON_ALWAYS_FLASH
-                        ImageCapture.FLASH_MODE_AUTO -> CONTROL_AE_MODE_ON_AUTO_FLASH
-                        else -> CONTROL_AE_MODE_ON
-                    }
+                    expectedAeMode
+                        ?: when (flashMode) {
+                            ImageCapture.FLASH_MODE_ON -> CONTROL_AE_MODE_ON_ALWAYS_FLASH
+                            ImageCapture.FLASH_MODE_AUTO -> CONTROL_AE_MODE_ON_AUTO_FLASH
+                            else -> CONTROL_AE_MODE_ON
+                        }
 
                 override fun onCaptureCompleted(
                     session: CameraCaptureSession,
@@ -251,7 +255,7 @@
                         isFlashModeSet = true
                     }
 
-                    if (request[CONTROL_AE_MODE] != expectedAeMode) {
+                    if (request[CONTROL_AE_MODE] != this.expectedAeMode) {
                         isAeModeExpected = false
                     }
                 }
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt
index c933712..7ef19fa 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt
@@ -42,6 +42,7 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.rule.GrantPermissionRule
 import androidx.test.uiautomator.UiDevice
+import androidx.testutils.withActivity
 import org.junit.After
 import org.junit.Assume
 import org.junit.Assume.assumeTrue
@@ -200,4 +201,21 @@
 
         return activityScenario
     }
+
+    @Test
+    fun checkPreviewUpdated_afterSwitchCamera() {
+        val activityScenario =
+            launchCamera2ExtensionsActivityAndWaitForCaptureSessionConfigured(config)
+        with(activityScenario) { // Launches activity
+            use { // Ensures that ActivityScenario is cleaned up properly
+                // Waits for preview to receive enough frames for its IdlingResource to idle.
+                waitForPreviewIdle()
+
+                withActivity { switchCamera() }
+
+                // Waits for preview to receive enough frames again after switching camera
+                waitForPreviewIdle()
+            }
+        }
+    }
 }
diff --git a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/Camera2ExtensionsActivity.kt b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/Camera2ExtensionsActivity.kt
index 5ca6d34..c9c78a7 100644
--- a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/Camera2ExtensionsActivity.kt
+++ b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/Camera2ExtensionsActivity.kt
@@ -620,24 +620,7 @@
         }
 
         val cameraSwitchButton = findViewById<Button>(R.id.Switch)
-        cameraSwitchButton.setOnClickListener {
-            val newCameraId = if (currentCameraId == backCameraId) frontCameraId else backCameraId
-
-            if (!isCameraSupportExtensions(newCameraId)) {
-                Toast.makeText(
-                        this,
-                        "Camera of the other lens facing doesn't support Camera2 extensions.",
-                        Toast.LENGTH_SHORT
-                    )
-                    .show()
-                return@setOnClickListener
-            }
-
-            enableUiControl(false)
-            currentCameraId = newCameraId
-            restartCamera = true
-            closeCaptureSessionAndCameraAsync()
-        }
+        cameraSwitchButton.setOnClickListener { switchCamera() }
 
         val captureButton = findViewById<Button>(R.id.Picture)
         captureButton.setOnClickListener {
@@ -647,6 +630,26 @@
         }
     }
 
+    @VisibleForTesting
+    fun switchCamera() {
+        val newCameraId = if (currentCameraId == backCameraId) frontCameraId else backCameraId
+
+        if (!isCameraSupportExtensions(newCameraId)) {
+            Toast.makeText(
+                    this,
+                    "Camera of the other lens facing doesn't support Camera2 extensions.",
+                    Toast.LENGTH_SHORT
+                )
+                .show()
+            return
+        }
+
+        enableUiControl(false)
+        currentCameraId = newCameraId
+        restartCamera = true
+        closeCaptureSessionAndCameraAsync()
+    }
+
     override fun onStart() {
         super.onStart()
         Log.d(TAG, "onStart()")
@@ -769,7 +772,7 @@
                         if (!oldCaptureSessionClosedDeferred.isCompleted) {
                             oldCaptureSessionClosedDeferred.complete(Unit)
                         }
-                        if (!keepCamera && synchronized(lock) { activityStopped }) {
+                        if (!keepCamera || synchronized(lock) { activityStopped }) {
                             Log.d(TAG, "Close camera++")
                             cameraDevice?.close()
                             cameraDevice = null
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml
index 400f759..d70e320 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml
@@ -81,8 +81,8 @@
     <string name="dial" msgid="3145707439707628311">"Marca"</string>
     <string name="address" msgid="9010635942573581302">"Adreça"</string>
     <string name="phone" msgid="2504766809811627577">"Telèfon"</string>
-    <string name="fail_start_nav" msgid="6921321606009212189">"S\'ha produït un error en iniciar la navegació"</string>
-    <string name="fail_start_dialer" msgid="1471602619507306261">"S\'ha produït un error en iniciar el telèfon"</string>
+    <string name="fail_start_nav" msgid="6921321606009212189">"Hi ha hagut un error en iniciar la navegació"</string>
+    <string name="fail_start_dialer" msgid="1471602619507306261">"Hi ha hagut un error en iniciar el telèfon"</string>
     <string name="car_hardware_demo_title" msgid="3679106197233262689">"Demostració del maquinari del cotxe"</string>
     <string name="car_hardware_info" msgid="1244783247616395012">"Informació sobre el maquinari del cotxe"</string>
     <string name="model_info" msgid="494224423025683030">"Informació del model"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml
index e50341f..0d07cf6 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml
@@ -94,7 +94,7 @@
     <string name="no_energy_profile_permission" msgid="4662285713731308888">"اجازه نمایه سوخت اعطا نشده است."</string>
     <string name="fuel_types" msgid="6811375173343218212">"انواع سوخت"</string>
     <string name="unavailable" msgid="3636401138255192934">"دردسترس نیست"</string>
-    <string name="ev_connector_types" msgid="735458637011996125">"انواع رابط‌های خودروی برقی"</string>
+    <string name="ev_connector_types" msgid="735458637011996125">"انواع رابط‌های خودرو برقی"</string>
     <string name="example_title" msgid="530257630320010494">"‏نمونه %d"</string>
     <string name="example_1_text" msgid="8631503055894800688">"رنگ این نوشتار "<annotation color="red">"قرمز"</annotation>" است"</string>
     <string name="example_2_text" msgid="1359373957397219102">"رنگ این نوشتار "<annotation color="green">"سبز"</annotation>" است"</string>
@@ -181,7 +181,7 @@
     <string name="no_energy_level_permission" msgid="1684773185095107825">"اجازه میزان سوخت اعطا نشده است."</string>
     <string name="no_speed_permission" msgid="5812532480922675390">"اجازه سرعت اعطا نشده است."</string>
     <string name="no_mileage_permission" msgid="4074779840599589847">"اجازه مسافت طی‌شده اعطا نشده است."</string>
-    <string name="no_ev_status_permission" msgid="933075402821938973">"اجازه وضعیت خودروی برقی اعطا نشده است."</string>
+    <string name="no_ev_status_permission" msgid="933075402821938973">"اجازه وضعیت خودرو برقی اعطا نشده است."</string>
     <string name="no_accelerometer_permission" msgid="896914448469117234">"اجازه شتاب‌سنج اعطا نشده است."</string>
     <string name="no_gyroscope_permission" msgid="665293140266771569">"اجازه ژیروسکوپ اعطا نشده است."</string>
     <string name="no_compass_permission" msgid="5162304489577567125">"اجازه قطب‌نما اعطا نشده است."</string>
@@ -190,7 +190,7 @@
     <string name="fetch_energy_level" msgid="1773415471137542832">"درحال واکشی میزان سوخت."</string>
     <string name="fetch_speed" msgid="7333830984597189627">"درحال واکشی سرعت."</string>
     <string name="fetch_mileage" msgid="7490131687788025123">"درحال واکشی مسافت طی‌شده."</string>
-    <string name="fetch_ev_status" msgid="2798910410830567052">"درحال واکشی وضعیت خودروی برقی."</string>
+    <string name="fetch_ev_status" msgid="2798910410830567052">"درحال واکشی وضعیت خودرو برقی."</string>
     <string name="fetch_accelerometer" msgid="697750041126810911">"درحال واکشی شتاب‌سنج."</string>
     <string name="fetch_gyroscope" msgid="7153155318827188539">"درحال واکشی ژیروسکوپ."</string>
     <string name="fetch_compass" msgid="7316188117590056717">"درحال واکشی قطب‌نما."</string>
@@ -204,8 +204,8 @@
     <string name="raw_speed" msgid="7295910214088983967">"سرعت اولیه"</string>
     <string name="unit" msgid="7697521583928135171">"واحد"</string>
     <string name="odometer" msgid="3925174645651546591">"مسافت‌شمار"</string>
-    <string name="ev_connected" msgid="2277845607662494696">"درگاه شارژ خودروی برقی متصل شد"</string>
-    <string name="ev_open" msgid="4916704450914519643">"درگاه شارژ خودروی برقی باز است"</string>
+    <string name="ev_connected" msgid="2277845607662494696">"درگاه شارژ خودرو برقی متصل شد"</string>
+    <string name="ev_open" msgid="4916704450914519643">"درگاه شارژ خودرو برقی باز است"</string>
     <string name="accelerometer" msgid="2084026313768299185">"شتاب‌سنج"</string>
     <string name="gyroscope" msgid="3428075828014504651">"ژیروسکوپ"</string>
     <string name="compass" msgid="7037367764762441245">"قطب‌نما"</string>
diff --git a/compose/animation/animation-core/build.gradle b/compose/animation/animation-core/build.gradle
index fac6444..4a6cdf1 100644
--- a/compose/animation/animation-core/build.gradle
+++ b/compose/animation/animation-core/build.gradle
@@ -29,12 +29,30 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.animation.core"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+        optimization {
+            it.consumerKeepRules.publish = true
+            it.consumerKeepRules.files.add(
+                    new File(project.projectDir, "proguard-rules.pro")
+            )
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -132,10 +150,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.animation.core"
-    buildTypes.configureEach {
-        consumerProguardFiles("proguard-rules.pro")
-    }
-}
diff --git a/compose/animation/animation/build.gradle b/compose/animation/animation/build.gradle
index fdc6664..56fd517 100644
--- a/compose/animation/animation/build.gradle
+++ b/compose/animation/animation/build.gradle
@@ -29,12 +29,24 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.animation"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -130,7 +142,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.animation"
-}
diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle
index a90bb95..54dd48b 100644
--- a/compose/foundation/foundation-layout/build.gradle
+++ b/compose/foundation/foundation-layout/build.gradle
@@ -28,12 +28,31 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.foundation.layout"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+
+        optimization {
+            it.consumerKeepRules.publish = true
+            it.consumerKeepRules.files.add(
+                new File(project.projectDir, "proguard-rules.pro")
+            )
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -122,10 +141,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.foundation.layout"
-    buildTypes.configureEach {
-        consumerProguardFiles("proguard-rules.pro")
-    }
-}
diff --git a/compose/material/material-ripple/build.gradle b/compose/material/material-ripple/build.gradle
index b6d5e76..9385d8d 100644
--- a/compose/material/material-ripple/build.gradle
+++ b/compose/material/material-ripple/build.gradle
@@ -28,12 +28,24 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.material.ripple"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -116,7 +128,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.material.ripple"
-}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt
index f33e079..31c5ed8 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt
@@ -89,11 +89,11 @@
         when (tooltipType) {
             TooltipType.Plain -> {
                 tooltip = { PlainTooltipTest() }
-                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider()
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider()
             }
             TooltipType.Rich -> {
                 tooltip = { RichTooltipTest() }
-                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider()
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider()
             }
         }
 
diff --git a/compose/material3/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/material3/integration/macrobenchmark/target/TooltipActivity.kt b/compose/material3/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/material3/integration/macrobenchmark/target/TooltipActivity.kt
index bf222cbc..a2f6eb1 100644
--- a/compose/material3/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/material3/integration/macrobenchmark/target/TooltipActivity.kt
+++ b/compose/material3/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/material3/integration/macrobenchmark/target/TooltipActivity.kt
@@ -37,7 +37,7 @@
         super.onCreate(savedInstanceState)
         setContent {
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = {
                     PlainTooltip(caretSize = TooltipDefaults.caretSize) {
                         Text("Tooltip Description")
diff --git a/compose/material3/material3-adaptive-navigation-suite/build.gradle b/compose/material3/material3-adaptive-navigation-suite/build.gradle
index 8871853..65c3958 100644
--- a/compose/material3/material3-adaptive-navigation-suite/build.gradle
+++ b/compose/material3/material3-adaptive-navigation-suite/build.gradle
@@ -29,12 +29,24 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.material3.adaptive.navigationsuite"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
@@ -97,10 +109,6 @@
     }
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.material3.adaptive.navigationsuite"
-}
 
 androidx {
     name = "Material Adaptive Navigation Suite"
diff --git a/compose/material3/material3-common/build.gradle b/compose/material3/material3-common/build.gradle
index 0572958..3eac2d7 100644
--- a/compose/material3/material3-common/build.gradle
+++ b/compose/material3/material3-common/build.gradle
@@ -31,11 +31,23 @@
 plugins {
     id("AndroidXPlugin")
     id("AndroidXComposePlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.material3.common"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -99,10 +111,6 @@
     }
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.material3.common"
-}
 
 androidx {
     name = "Compose Material 3 Common"
diff --git a/compose/material3/material3-window-size-class/build.gradle b/compose/material3/material3-window-size-class/build.gradle
index a943601..46fb47e 100644
--- a/compose/material3/material3-window-size-class/build.gradle
+++ b/compose/material3/material3-window-size-class/build.gradle
@@ -28,12 +28,24 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.material3.windowsizeclass"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -114,7 +126,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.material3.windowsizeclass"
-}
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index a43c6e0..28407dd 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -1929,7 +1929,8 @@
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class SheetState {
-    ctor public SheetState(boolean skipPartiallyExpanded, androidx.compose.ui.unit.Density density, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, optional boolean skipHiddenState);
+    ctor @Deprecated public SheetState(boolean skipPartiallyExpanded, androidx.compose.ui.unit.Density density, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, optional boolean skipHiddenState);
+    ctor public SheetState(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function0<java.lang.Float> positionalThreshold, kotlin.jvm.functions.Function0<java.lang.Float> velocityThreshold, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, optional boolean skipHiddenState);
     method public suspend Object? expand(kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method public androidx.compose.material3.SheetValue getCurrentValue();
     method public boolean getHasExpandedState();
@@ -1951,7 +1952,8 @@
   }
 
   public static final class SheetState.Companion {
-    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, androidx.compose.ui.unit.Density density, boolean skipHiddenState);
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function0<java.lang.Float> positionalThreshold, kotlin.jvm.functions.Function0<java.lang.Float> velocityThreshold, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, boolean skipHiddenState);
+    method @Deprecated public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, androidx.compose.ui.unit.Density density, boolean skipHiddenState);
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public enum SheetValue {
@@ -2691,8 +2693,9 @@
     method public float getPlainTooltipMaxWidth();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRichTooltipContainerShape();
     method public float getRichTooltipMaxWidth();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberPlainTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberRichTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberPlainTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberRichTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors(optional long containerColor, optional long contentColor, optional long titleContentColor, optional long actionContentColor);
     property public final long caretSize;
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index a43c6e0..28407dd 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -1929,7 +1929,8 @@
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class SheetState {
-    ctor public SheetState(boolean skipPartiallyExpanded, androidx.compose.ui.unit.Density density, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, optional boolean skipHiddenState);
+    ctor @Deprecated public SheetState(boolean skipPartiallyExpanded, androidx.compose.ui.unit.Density density, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, optional boolean skipHiddenState);
+    ctor public SheetState(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function0<java.lang.Float> positionalThreshold, kotlin.jvm.functions.Function0<java.lang.Float> velocityThreshold, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, optional boolean skipHiddenState);
     method public suspend Object? expand(kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method public androidx.compose.material3.SheetValue getCurrentValue();
     method public boolean getHasExpandedState();
@@ -1951,7 +1952,8 @@
   }
 
   public static final class SheetState.Companion {
-    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, androidx.compose.ui.unit.Density density, boolean skipHiddenState);
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function0<java.lang.Float> positionalThreshold, kotlin.jvm.functions.Function0<java.lang.Float> velocityThreshold, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, boolean skipHiddenState);
+    method @Deprecated public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange, androidx.compose.ui.unit.Density density, boolean skipHiddenState);
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public enum SheetValue {
@@ -2691,8 +2693,9 @@
     method public float getPlainTooltipMaxWidth();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRichTooltipContainerShape();
     method public float getRichTooltipMaxWidth();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberPlainTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberRichTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberPlainTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberRichTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors(optional long containerColor, optional long contentColor, optional long titleContentColor, optional long actionContentColor);
     property public final long caretSize;
diff --git a/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt b/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt
index ec5eede..9e4c440 100644
--- a/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt
+++ b/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt
@@ -65,7 +65,7 @@
             val textFieldTooltipState = rememberTooltipState()
             val scope = rememberCoroutineScope()
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = { PlainTooltip { Text(textFieldTooltipText) } },
                 state = textFieldTooltipState
             ) {
@@ -96,7 +96,7 @@
         LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) {
             items(listData) { item ->
                 TooltipBox(
-                    positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                     tooltip = { PlainTooltip { Text("${item.itemName} added to list") } },
                     state = item.addedTooltipState
                 ) {
@@ -115,7 +115,7 @@
             headlineContent = { Text(itemName) },
             trailingContent = {
                 TooltipBox(
-                    positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                     tooltip = { PlainTooltip { Text("Delete $itemName") } },
                     state = rememberTooltipState(),
                     enableUserInput = true
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt
index bd37b75..1d8809e 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt
@@ -50,7 +50,7 @@
 @Composable
 fun PlainTooltipSample() {
     TooltipBox(
-        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
         tooltip = { PlainTooltip { Text("Add to favorites") } },
         state = rememberTooltipState()
     ) {
@@ -69,7 +69,7 @@
     val scope = rememberCoroutineScope()
     Column(horizontalAlignment = Alignment.CenterHorizontally) {
         TooltipBox(
-            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
             tooltip = { PlainTooltip { Text("Add to list") } },
             state = tooltipState
         ) {
@@ -87,7 +87,7 @@
 @Composable
 fun PlainTooltipWithCaret() {
     TooltipBox(
-        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
         tooltip = {
             PlainTooltip(caretSize = TooltipDefaults.caretSize) { Text("Add to favorites") }
         },
@@ -104,7 +104,7 @@
 @Composable
 fun PlainTooltipWithCustomCaret() {
     TooltipBox(
-        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
         tooltip = { PlainTooltip(caretSize = DpSize(24.dp, 12.dp)) { Text("Add to favorites") } },
         state = rememberTooltipState()
     ) {
@@ -121,7 +121,7 @@
     val tooltipState = rememberTooltipState(isPersistent = true)
     val scope = rememberCoroutineScope()
     TooltipBox(
-        positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
         tooltip = {
             RichTooltip(
                 title = { Text(richTooltipSubheadText) },
@@ -150,7 +150,7 @@
     val scope = rememberCoroutineScope()
     Column(horizontalAlignment = Alignment.CenterHorizontally) {
         TooltipBox(
-            positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
             tooltip = {
                 RichTooltip(
                     title = { Text(richTooltipSubheadText) },
@@ -181,7 +181,7 @@
     val tooltipState = rememberTooltipState(isPersistent = true)
     val scope = rememberCoroutineScope()
     TooltipBox(
-        positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
         tooltip = {
             RichTooltip(
                 title = { Text(richTooltipSubheadText) },
@@ -210,7 +210,7 @@
     val tooltipState = rememberTooltipState(isPersistent = true)
     val scope = rememberCoroutineScope()
     TooltipBox(
-        positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
         tooltip = {
             RichTooltip(
                 title = { Text(richTooltipSubheadText) },
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt
index 40418e9..16a6375 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt
@@ -252,7 +252,12 @@
                 skipPartiallyExpanded = false,
                 skipHiddenState = true,
                 initialValue = SheetValue.PartiallyExpanded,
-                density = rule.density
+                positionalThreshold = {
+                    with(rule.density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                },
+                velocityThreshold = {
+                    with(rule.density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                },
             )
         rule.setContent {
             scope = rememberCoroutineScope()
@@ -923,7 +928,16 @@
             )
         var sheetCoords: LayoutCoordinates? = null
         var rootCoords: LayoutCoordinates? = null
-        val state = SheetState(false, density = Density(1f))
+        val state =
+            SheetState(
+                skipPartiallyExpanded = false,
+                positionalThreshold = {
+                    with(rule.density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                },
+                velocityThreshold = {
+                    with(rule.density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                },
+            )
         var sheetValue by mutableStateOf(SheetValue.Hidden)
         rule.setContent {
             Box(Modifier.onGloballyPositioned { rootCoords = it }.offset { offset }) {
@@ -983,7 +997,16 @@
                 IntOffset(100, 10),
             )
         var sheetCoords: LayoutCoordinates? = null
-        val state = SheetState(false, density = Density(1f))
+        val state =
+            SheetState(
+                skipPartiallyExpanded = false,
+                positionalThreshold = {
+                    with(rule.density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                },
+                velocityThreshold = {
+                    with(rule.density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                },
+            )
         var sheetValue by mutableStateOf(SheetValue.Hidden)
         rule.setContent {
             LaunchedEffect(sheetValue) {
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
index 6453fe4..a6dc9a7 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
@@ -84,6 +84,7 @@
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import org.junit.Assume.assumeNotNull
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -187,7 +188,11 @@
         rule.onNodeWithTag(EDMTag).assertIsDisplayed()
         rule.onNodeWithTag(MenuItemTag).assertIsDisplayed()
 
-        UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressBack()
+        val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+        // First back closes keyboard
+        device.pressBack()
+        // Second back closes menu
+        device.pressBack()
 
         rule.onNodeWithTag(TFTag).assertIsDisplayed()
         rule.onNodeWithTag(MenuItemTag).assertDoesNotExist()
@@ -261,6 +266,7 @@
         rule.onNodeWithTag(MenuItemTag).assertDoesNotExist()
     }
 
+    @Ignore("b/374850853")
     @Test
     fun edm_editable_collapsesOnEscapePress() {
         rule.setMaterialContent(lightColorScheme()) {
@@ -531,6 +537,46 @@
     }
 
     @Test
+    fun edm_anchorTypeIsUpdated_evenIfTextFieldIsNotClicked() {
+        var expanded by mutableStateOf(false)
+        var type: ExposedDropdownMenuAnchorType? = null
+        rule.setMaterialContent(lightColorScheme()) {
+            ExposedDropdownMenuBox(
+                expanded = expanded,
+                onExpandedChange = { expanded = it },
+            ) {
+                TextField(
+                    modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable),
+                    state = rememberTextFieldState(),
+                    lineLimits = TextFieldLineLimits.SingleLine,
+                    label = { Text("Label") },
+                    trailingIcon = {
+                        ExposedDropdownMenuDefaults.TrailingIcon(
+                            expanded = expanded,
+                            modifier =
+                                Modifier.menuAnchor(
+                                    ExposedDropdownMenuAnchorType.SecondaryEditable
+                                ),
+                        )
+                    }
+                )
+                ExposedDropdownMenu(
+                    expanded = expanded,
+                    onDismissRequest = { expanded = false },
+                ) {
+                    DropdownMenuItem(
+                        text = { Text(OptionName) },
+                        onClick = {},
+                    )
+                }
+                SideEffect { type = anchorType }
+            }
+        }
+        rule.runOnIdle { expanded = true }
+        assertThat(type).isEqualTo(ExposedDropdownMenuAnchorType.PrimaryEditable)
+    }
+
+    @Test
     fun edm_widthMatchesTextFieldWidth() {
         var textFieldBounds by mutableStateOf(Rect.Zero)
         var menuBounds by mutableStateOf(Rect.Zero)
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
index 8fc3131..1293b79 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
@@ -125,9 +125,20 @@
     @Test
     fun modalBottomSheet_isDismissedOnTapOutside() {
         var showBottomSheet by mutableStateOf(true)
-        val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
+        lateinit var sheetState: SheetState
 
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = false,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             if (showBottomSheet) {
                 ModalBottomSheet(
                     sheetState = sheetState,
@@ -160,8 +171,16 @@
     @Test
     fun modalBottomSheet_isDismissedOnSwipeDown() {
         var showBottomSheet by mutableStateOf(true)
-        val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
-
+        val sheetState =
+            SheetState(
+                skipPartiallyExpanded = false,
+                positionalThreshold = {
+                    with(rule.density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                },
+                velocityThreshold = {
+                    with(rule.density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                },
+            )
         rule.setContent {
             if (showBottomSheet) {
                 ModalBottomSheet(
@@ -362,9 +381,20 @@
     @Test
     fun modalBottomSheet_shortSheet_isDismissedOnBackPress() {
         var showBottomSheet by mutableStateOf(true)
-        val sheetState = SheetState(skipPartiallyExpanded = true, density = rule.density)
+        lateinit var sheetState: SheetState
 
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = true,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher
             if (showBottomSheet) {
                 ModalBottomSheet(
@@ -395,9 +425,20 @@
     @Test
     fun modalBottomSheet_tallSheet_isDismissedOnBackPress() {
         var showBottomSheet by mutableStateOf(true)
-        val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
+        lateinit var sheetState: SheetState
 
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = false,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher
             if (showBottomSheet) {
                 ModalBottomSheet(
@@ -611,10 +652,21 @@
     fun modalBottomSheet_missingAnchors_findsClosest() {
         val topTag = "ModalBottomSheetLayout"
         var showShortContent by mutableStateOf(false)
-        val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
+        lateinit var sheetState: SheetState
         lateinit var scope: CoroutineScope
 
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = false,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             scope = rememberCoroutineScope()
             ModalBottomSheet(
                 onDismissRequest = {},
@@ -790,8 +842,20 @@
     @Test
     fun modalBottomSheet_testParialExpandReturnsIllegalStateException_whenSkipPartialExpanded() {
         lateinit var scope: CoroutineScope
-        val bottomSheetState = SheetState(skipPartiallyExpanded = true, density = rule.density)
+        lateinit var bottomSheetState: SheetState
+
         rule.setContent {
+            val density = LocalDensity.current
+            bottomSheetState =
+                SheetState(
+                    skipPartiallyExpanded = true,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             scope = rememberCoroutineScope()
             ModalBottomSheet(
                 onDismissRequest = {},
@@ -931,10 +995,22 @@
 
     @Test
     fun modalBottomSheet_shortSheet_anchorChangeHandler_previousTargetNotInAnchors_reconciles() {
-        val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
         var hasSheetContent by mutableStateOf(false) // Start out with empty sheet content
         lateinit var scope: CoroutineScope
+        lateinit var sheetState: SheetState
+
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = false,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             scope = rememberCoroutineScope()
 
             ModalBottomSheet(
@@ -968,10 +1044,22 @@
 
     @Test
     fun modalBottomSheet_tallSheet_anchorChangeHandler_previousTargetNotInAnchors_reconciles() {
-        val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
         var hasSheetContent by mutableStateOf(false) // Start out with empty sheet content
         lateinit var scope: CoroutineScope
+        lateinit var sheetState: SheetState
+
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = false,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             scope = rememberCoroutineScope()
             ModalBottomSheet(
                 onDismissRequest = {},
@@ -1006,8 +1094,6 @@
     fun modalBottomSheet_callsOnDismissRequest_onNestedScrollFling() {
         var callCount by mutableStateOf(0)
         val expectedCallCount = 1
-        val sheetState = SheetState(skipPartiallyExpanded = true, density = rule.density)
-
         val nestedScrollDispatcher = NestedScrollDispatcher()
         val nestedScrollConnection =
             object : NestedScrollConnection {
@@ -1015,7 +1101,20 @@
             }
         lateinit var scope: CoroutineScope
 
+        lateinit var sheetState: SheetState
+
         rule.setContent {
+            val density = LocalDensity.current
+            sheetState =
+                SheetState(
+                    skipPartiallyExpanded = true,
+                    positionalThreshold = {
+                        with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                    },
+                    velocityThreshold = {
+                        with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                    },
+                )
             scope = rememberCoroutineScope()
             ModalBottomSheet(
                 onDismissRequest = { callCount += 1 },
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
index feb118a..f2b416d 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
@@ -120,7 +120,7 @@
     private fun PlainTooltipTest() {
         val tooltipState = rememberTooltipState()
         TooltipBox(
-            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
             tooltip = {
                 PlainTooltip(modifier = Modifier.testTag(TooltipTestTag)) {
                     Text("Tooltip Description")
@@ -137,7 +137,7 @@
     private fun RichTooltipTest() {
         val tooltipState = rememberTooltipState(isPersistent = true)
         TooltipBox(
-            positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
             tooltip = {
                 RichTooltip(
                     title = { Text("Title") },
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipTest.kt
index 0cfc573..fccc9c2 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TooltipTest.kt
@@ -465,9 +465,7 @@
 
         // Plain tooltip positioning
         lateinit var positionProvider: PopupPositionProvider
-        rule.setContent {
-            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider()
-        }
+        rule.setContent { positionProvider = TooltipDefaults.rememberTooltipPositionProvider() }
 
         val tooltipPosition =
             positionProvider.calculatePosition(
@@ -500,7 +498,7 @@
 
         // Rich tooltip positioning
         lateinit var positionProvider: PopupPositionProvider
-        rule.setContent { positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider() }
+        rule.setContent { positionProvider = TooltipDefaults.rememberTooltipPositionProvider() }
 
         val tooltipPosition =
             positionProvider.calculatePosition(
@@ -521,7 +519,7 @@
         var anchorBounds = Rect.Zero
         rule.setContent {
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 state = rememberTooltipState(initialIsVisible = true, isPersistent = true),
                 tooltip = {
                     PlainTooltip(
@@ -565,7 +563,7 @@
         var anchorBounds = Rect.Zero
         rule.setContent {
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 state = rememberTooltipState(initialIsVisible = true, isPersistent = true),
                 tooltip = {
                     RichTooltip(
@@ -615,7 +613,7 @@
             topState = rememberTooltipState(isPersistent = true)
             bottomState = rememberTooltipState(isPersistent = true)
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = {
                     RichTooltip(
                         title = {
@@ -636,7 +634,7 @@
             scope.launch { topState.show() }
 
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = {
                     RichTooltip(
                         title = {
@@ -679,7 +677,7 @@
             val scope = rememberCoroutineScope()
             topState = rememberTooltipState(isPersistent = true, mutatorMutex = MutatorMutex())
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = {
                     RichTooltip(
                         title = {
@@ -701,7 +699,7 @@
 
             bottomState = rememberTooltipState(isPersistent = true, mutatorMutex = MutatorMutex())
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = {
                     RichTooltip(
                         title = {
@@ -741,7 +739,7 @@
         tooltipState: TooltipState = rememberTooltipState(),
     ) {
         TooltipBox(
-            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
             tooltip = {
                 PlainTooltip(
                     modifier = modifier.testTag(ContainerTestTag),
@@ -763,7 +761,7 @@
         tooltipState: TooltipState = rememberTooltipState(action != null),
     ) {
         TooltipBox(
-            positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
             tooltip = {
                 RichTooltip(
                     title = title,
@@ -782,7 +780,7 @@
     fun plainTooltip_withClickable_hasCorrectSemantics() {
         rule.setMaterialContent(lightColorScheme()) {
             TooltipBox(
-                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
                 tooltip = {
                     PlainTooltip(
                         modifier = Modifier.testTag(ContainerTestTag),
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
index b4fa43b..edfc828 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
@@ -161,21 +161,29 @@
     fun determinateLinearWavyProgressIndicator_sizeModifier() {
         val expectedWidth = 100.dp
         val expectedHeight = 10.dp
-        val expectedSize =
-            with(rule.density) { IntSize(expectedWidth.roundToPx(), expectedHeight.roundToPx()) }
         val tag = "linear"
-        var trackColor = Color.Unspecified
-        var progressColor = Color.Unspecified
-        rule.setContent {
-            trackColor = ProgressIndicatorDefaults.linearTrackColor
-            progressColor = ProgressIndicatorDefaults.linearColor
-
-            Box(Modifier.testTag(tag)) {
+        val contentToTest =
+            rule.setMaterialContentForSizeAssertions {
                 LinearWavyProgressIndicator(
-                    modifier = Modifier.size(expectedWidth, expectedHeight),
+                    modifier = Modifier.size(expectedWidth, expectedHeight).testTag(tag),
                     progress = { 0.5f }
                 )
             }
+
+        contentToTest.assertWidthIsEqualTo(expectedWidth).assertHeightIsEqualTo(expectedHeight)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun determinateLinearWavyProgressIndicator_colors() {
+        val tag = "linear"
+        var trackColor = Color.Unspecified
+        var progressColor = Color.Unspecified
+        rule.setMaterialContentForSizeAssertions {
+            trackColor = ProgressIndicatorDefaults.linearTrackColor
+            progressColor = ProgressIndicatorDefaults.linearColor
+
+            Box(Modifier.testTag(tag)) { LinearWavyProgressIndicator(progress = { 0.5f }) }
         }
 
         rule
@@ -183,11 +191,6 @@
             .captureToImage()
             .assertContainsColor(trackColor)
             .assertContainsColor(progressColor)
-            .toPixelMap()
-            .let {
-                assertEquals(expectedSize.width, it.width)
-                assertEquals(expectedSize.height, it.height)
-            }
     }
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -195,24 +198,29 @@
     fun indeterminateLinearWavyProgressIndicator_sizeModifier() {
         val expectedWidth = 100.dp
         val expectedHeight = 10.dp
-        val expectedSize =
-            with(rule.density) { IntSize(expectedWidth.roundToPx(), expectedHeight.roundToPx()) }
-        rule.mainClock.autoAdvance = false
         val tag = "linear"
-        rule.setContent {
-            Box(Modifier.testTag(tag)) {
+        val contentToTest =
+            rule.setMaterialContentForSizeAssertions {
                 LinearWavyProgressIndicator(
-                    modifier = Modifier.size(expectedWidth, expectedHeight),
-                    color = Color.Blue
+                    modifier = Modifier.size(expectedWidth, expectedHeight).testTag(tag),
                 )
             }
+
+        contentToTest.assertWidthIsEqualTo(expectedWidth).assertHeightIsEqualTo(expectedHeight)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun indeterminateLinearWavyProgressIndicator_colors() {
+        rule.mainClock.autoAdvance = false
+        val tag = "linear"
+        rule.setMaterialContentForSizeAssertions {
+            Box(Modifier.testTag(tag)) { LinearWavyProgressIndicator(color = Color.Blue) }
         }
 
         rule.mainClock.advanceTimeBy(300)
 
         rule.onNodeWithTag(tag).captureToImage().toPixelMap().let {
-            assertEquals(expectedSize.width, it.width)
-            assertEquals(expectedSize.height, it.height)
             // Assert that a center pixel relatively at the start of the path has the right
             // progress color.
             it.assertPixelColor(Color.Blue, 5, it.height / 2)
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt
index 9c9a97b..d67fed8 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt
@@ -68,6 +68,8 @@
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.layout.positionInWindow
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalSoftwareKeyboardController
@@ -168,6 +170,13 @@
                 ): Modifier =
                     this.focusRequester(focusRequester)
                         .then(
+                            ExposedDropdownMenuAnchorElement {
+                                if (type.hasGreaterOrEqualPriorityThan(anchorTypeState.value)) {
+                                    anchorTypeState.value = type
+                                }
+                            }
+                        )
+                        .then(
                             if (!enabled) Modifier
                             else
                                 Modifier.expandable(
@@ -516,6 +525,17 @@
     override fun toString(): String = name
 }
 
+private fun ExposedDropdownMenuAnchorType.hasGreaterOrEqualPriorityThan(
+    that: ExposedDropdownMenuAnchorType
+): Boolean =
+    when (this) {
+        ExposedDropdownMenuAnchorType.PrimaryNotEditable,
+        ExposedDropdownMenuAnchorType.PrimaryEditable -> true
+        ExposedDropdownMenuAnchorType.SecondaryEditable ->
+            that == ExposedDropdownMenuAnchorType.SecondaryEditable
+        else -> false
+    }
+
 @Deprecated(
     message = "Renamed to ExposedDropdownMenuAnchorType",
     replaceWith = ReplaceWith("ExposedDropdownMenuAnchorType"),
@@ -1434,6 +1454,29 @@
     }
 }
 
+private data class ExposedDropdownMenuAnchorElement(
+    val updateStateOnAttach: () -> Unit,
+) : ModifierNodeElement<ExposedDropdownMenuAnchorNode>() {
+    override fun create() = ExposedDropdownMenuAnchorNode(updateStateOnAttach)
+
+    override fun update(node: ExposedDropdownMenuAnchorNode) {
+        node.updateStateOnAttach = updateStateOnAttach
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "exposedDropdownMenuAnchorType"
+        properties["updateStateOnAttach"] = updateStateOnAttach
+    }
+}
+
+private class ExposedDropdownMenuAnchorNode(
+    var updateStateOnAttach: () -> Unit,
+) : Modifier.Node() {
+    override fun onAttach() {
+        updateStateOnAttach()
+    }
+}
+
 private fun Modifier.expandable(
     expanded: Boolean,
     onExpandedChange: () -> Unit,
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Tooltip.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Tooltip.android.kt
index c2c9412..ffa265c 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Tooltip.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Tooltip.android.kt
@@ -125,7 +125,6 @@
             val configuration = LocalConfiguration.current
             Modifier.drawCaret { anchorLayoutCoordinates ->
                     drawCaretWithPath(
-                        CaretType.Plain,
                         density,
                         configuration,
                         containerColor,
@@ -253,7 +252,6 @@
             val configuration = LocalConfiguration.current
             Modifier.drawCaret { anchorLayoutCoordinates ->
                     drawCaretWithPath(
-                        CaretType.Rich,
                         density,
                         configuration,
                         elevatedColor,
@@ -315,7 +313,6 @@
 
 @ExperimentalMaterial3Api
 private fun CacheDrawScope.drawCaretWithPath(
-    caretType: CaretType,
     density: Density,
     configuration: Configuration,
     containerColor: Color,
@@ -351,42 +348,27 @@
                 tooltipHeight
             }
 
-        val position: Offset
-        if (caretType == CaretType.Plain) {
-            position =
-                if (anchorMid + tooltipWidth / 2 > screenWidthPx) {
-                    // Caret needs to be near the right
-                    val anchorMidFromRightScreenEdge = screenWidthPx - anchorMid
-                    val caretX = tooltipWidth - anchorMidFromRightScreenEdge
-                    Offset(caretX, caretY)
-                } else {
-                    // Caret needs to be near the left
-                    val tooltipLeft = anchorLeft - (this.size.width / 2 - anchorWidth / 2)
-                    val caretX = anchorMid - maxOf(tooltipLeft, 0f)
-                    Offset(caretX, caretY)
-                }
-        } else {
-            // Default the caret to the left
-            var preferredPosition = Offset(anchorMid - anchorLeft, caretY)
-            if (anchorLeft + tooltipWidth > screenWidthPx) {
-                // Need to move the caret to the right
-                preferredPosition = Offset(anchorMid - (anchorRight - tooltipWidth), caretY)
-                if (anchorRight - tooltipWidth < 0) {
-                    // Need to center the caret
-                    // Caret might need to be offset depending on where
-                    // the tooltip is placed relative to the anchor
-                    if (anchorLeft - tooltipWidth / 2 + anchorWidth / 2 <= 0) {
-                        preferredPosition = Offset(anchorMid, caretY)
-                    } else if (anchorRight + tooltipWidth / 2 - anchorWidth / 2 >= screenWidthPx) {
-                        val anchorMidFromRightScreenEdge = screenWidthPx - anchorMid
-                        val caretX = tooltipWidth - anchorMidFromRightScreenEdge
-                        preferredPosition = Offset(caretX, caretY)
-                    } else {
-                        preferredPosition = Offset(tooltipWidth / 2, caretY)
-                    }
-                }
+        // Default the caret to be in the middle
+        // caret might need to be offset depending on where
+        // the tooltip is placed relative to the anchor
+        var position: Offset =
+            if (anchorLeft - tooltipWidth / 2 + anchorWidth / 2 <= 0) {
+                Offset(anchorMid, caretY)
+            } else if (anchorRight + tooltipWidth / 2 - anchorWidth / 2 >= screenWidthPx) {
+                val anchorMidFromRightScreenEdge = screenWidthPx - anchorMid
+                val caretX = tooltipWidth - anchorMidFromRightScreenEdge
+                Offset(caretX, caretY)
+            } else {
+                Offset(tooltipWidth / 2, caretY)
             }
-            position = preferredPosition
+        if (anchorMid - tooltipWidth / 2 < 0) {
+            // The tooltip needs to be start aligned if it would collide with the left side of
+            // screen.
+            position = Offset(anchorMid - anchorLeft, caretY)
+        } else if (anchorMid + tooltipWidth / 2 > screenWidthPx) {
+            // The tooltip needs to be end aligned if it would collide with the right side of the
+            // screen.
+            position = Offset(anchorMid - (anchorRight - tooltipWidth), caretY)
         }
 
         if (isCaretTop) {
@@ -415,9 +397,3 @@
         }
     }
 }
-
-@ExperimentalMaterial3Api
-private enum class CaretType {
-    Plain,
-    Rich
-}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DragHandle.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DragHandle.kt
new file mode 100644
index 0000000..da5127e
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DragHandle.kt
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2024 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.material3
+
+import androidx.compose.foundation.gestures.PressGestureScope
+import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.hoverable
+import androidx.compose.foundation.indication
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.collectIsDraggedAsState
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.DragHandleDefaults.dragHandleColors
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+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.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.graphics.isSpecified
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.layout
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastRoundToInt
+
+@Composable
+internal fun VerticalDragHandle(
+    modifier: Modifier = Modifier,
+    sizes: DragHandleSizes = DragHandleDefaults.DefaultDragHandleSizes,
+    colors: DragHandleColors = MaterialTheme.colorScheme.dragHandleColors(),
+    shapes: DragHandleShapes = DragHandleDefaults.DefaultDragHandleShapes,
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+) {
+    val isDragged by interactionSource.collectIsDraggedAsState()
+    var isPressed by remember { mutableStateOf(false) }
+    Box(
+        modifier =
+            modifier
+                .minimumInteractiveComponentSize()
+                .hoverable(interactionSource)
+                .pressable(interactionSource) { _ ->
+                    isPressed = true
+                    tryAwaitRelease()
+                    isPressed = false
+                }
+                .graphicsLayer {
+                    shape = if (isDragged || isPressed) shapes.pressedShape else shapes.defaultShape
+                    clip = true
+                }
+                .layout { measurable, _ ->
+                    val dragHandleSize =
+                        if (isDragged || isPressed) {
+                                sizes.pressedSize
+                            } else {
+                                sizes.defaultSize
+                            }
+                            .toSize()
+                    // set constraints here to be the size needed
+                    val placeable =
+                        measurable.measure(
+                            Constraints.fixed(
+                                dragHandleSize.width.fastRoundToInt(),
+                                dragHandleSize.height.fastRoundToInt()
+                            )
+                        )
+                    layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) }
+                }
+                .drawBehind {
+                    drawRect(
+                        if (isDragged || isPressed) colors.pressedColor else colors.defaultColor
+                    )
+                }
+                .indication(interactionSource, ripple())
+    )
+}
+
+@Immutable
+internal class DragHandleColors(val defaultColor: Color, val pressedColor: Color) {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is DragHandleColors) return false
+        if (defaultColor != other.defaultColor) return false
+        if (pressedColor != other.pressedColor) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = defaultColor.hashCode()
+        result = 31 * result + pressedColor.hashCode()
+        return result
+    }
+}
+
+@Immutable
+internal class DragHandleShapes(val defaultShape: Shape, val pressedShape: Shape) {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is DragHandleShapes) return false
+        if (defaultShape != other.defaultShape) return false
+        if (pressedShape != other.pressedShape) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = defaultShape.hashCode()
+        result = 31 * result + pressedShape.hashCode()
+        return result
+    }
+}
+
+@Immutable
+internal class DragHandleSizes(val defaultSize: DpSize, val pressedSize: DpSize) {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is DragHandleSizes) return false
+        if (defaultSize != other.defaultSize) return false
+        if (pressedSize != other.pressedSize) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = defaultSize.hashCode()
+        result = 31 * result + pressedSize.hashCode()
+        return result
+    }
+}
+
+// TODO(b/343194663): Introduce tokens and theming
+internal object DragHandleDefaults {
+    @Composable
+    fun dragHandleColors(
+        defaultColor: Color = Color.Unspecified,
+        pressedColor: Color = Color.Unspecified
+    ): DragHandleColors = MaterialTheme.colorScheme.dragHandleColors(defaultColor, pressedColor)
+
+    fun dragHandleShapes(
+        defaultShape: Shape = CircleShape,
+        pressedShape: Shape = RoundedCornerShape(12.dp)
+    ): DragHandleShapes = DragHandleShapes(defaultShape, pressedShape)
+
+    fun dragHandleSizes(
+        defaultSize: DpSize = DpSize(4.dp, 48.dp),
+        pressedSize: DpSize = DpSize(12.dp, 52.dp)
+    ): DragHandleSizes = DragHandleSizes(defaultSize, pressedSize)
+
+    internal fun ColorScheme.dragHandleColors(
+        defaultColor: Color = Color.Unspecified,
+        pressedColor: Color = Color.Unspecified
+    ): DragHandleColors =
+        DragHandleColors(
+            if (defaultColor.isSpecified) defaultColor else outline,
+            if (pressedColor.isSpecified) pressedColor else onSurface
+        )
+
+    internal val DefaultDragHandleShapes = dragHandleShapes()
+
+    internal val DefaultDragHandleSizes = dragHandleSizes()
+}
+
+private fun Modifier.pressable(
+    interactionSource: MutableInteractionSource,
+    onPress: suspend PressGestureScope.(Offset) -> Unit,
+): Modifier = pointerInput(interactionSource) { detectTapGestures(onPress = onPress) }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Label.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Label.kt
index 27ac94b..b3a8bee 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Label.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Label.kt
@@ -41,7 +41,7 @@
 
 /**
  * Label component that will append a [label] to [content]. The positioning logic uses
- * [TooltipDefaults.rememberPlainTooltipPositionProvider].
+ * [TooltipDefaults.rememberTooltipPositionProvider].
  *
  * Label appended to thumbs of Slider:
  *
@@ -71,7 +71,7 @@
     @Suppress("NAME_SHADOWING")
     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
     // Has the same positioning logic as PlainTooltips
-    val positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider()
+    val positionProvider = TooltipDefaults.rememberTooltipPositionProvider()
     val state =
         if (isPersistent) remember { LabelStateImpl() }
         else rememberBasicTooltipState(mutatorMutex = MutatorMutex())
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt
index 12620b9..66d3d8d 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt
@@ -69,8 +69,15 @@
  *   should be skipped. If true, the sheet will always expand to the [Expanded] state and move to
  *   the [Hidden] state if available when hiding the sheet, either programmatically or by user
  *   interaction.
+ * @param positionalThreshold The positional threshold, in px, to be used when calculating the
+ *   target state while a drag is in progress and when settling after the drag ends. This is the
+ *   distance from the start of a transition. It will be, depending on the direction of the
+ *   interaction, added or subtracted from/to the origin offset. It should always be a positive
+ *   value.
+ * @param velocityThreshold The velocity threshold (in px per second) that the end velocity has to
+ *   exceed in order to animate to the next state, even if the [positionalThreshold] has not been
+ *   reached.
  * @param initialValue The initial value of the state.
- * @param density The density that this state can use to convert values to and from dp.
  * @param confirmValueChange Optional callback invoked to confirm or veto a pending state change.
  * @param skipHiddenState Whether the hidden state should be skipped. If true, the sheet will always
  *   expand to the [Expanded] state and move to the [PartiallyExpanded] if available, either
@@ -80,11 +87,13 @@
 @ExperimentalMaterial3Api
 class SheetState(
     internal val skipPartiallyExpanded: Boolean,
-    density: Density,
+    positionalThreshold: () -> Float,
+    velocityThreshold: () -> Float,
     initialValue: SheetValue = Hidden,
     confirmValueChange: (SheetValue) -> Boolean = { true },
     internal val skipHiddenState: Boolean = false,
 ) {
+
     init {
         if (skipPartiallyExpanded) {
             require(initialValue != PartiallyExpanded) {
@@ -270,8 +279,8 @@
             initialValue = initialValue,
             animationSpec = { anchoredDraggableMotionSpec },
             confirmValueChange = confirmValueChange,
-            positionalThreshold = { with(density) { 56.dp.toPx() } },
-            velocityThreshold = { with(density) { 125.dp.toPx() } },
+            positionalThreshold = { positionalThreshold() },
+            velocityThreshold = velocityThreshold,
         )
 
     internal val offset: Float
@@ -285,8 +294,9 @@
         /** The default [Saver] implementation for [SheetState]. */
         fun Saver(
             skipPartiallyExpanded: Boolean,
+            positionalThreshold: () -> Float,
+            velocityThreshold: () -> Float,
             confirmValueChange: (SheetValue) -> Boolean,
-            density: Density,
             skipHiddenState: Boolean,
         ) =
             Saver<SheetState, SheetValue>(
@@ -294,14 +304,53 @@
                 restore = { savedValue ->
                     SheetState(
                         skipPartiallyExpanded,
-                        density,
+                        positionalThreshold,
+                        velocityThreshold,
                         savedValue,
                         confirmValueChange,
                         skipHiddenState,
                     )
                 }
             )
+
+        @Deprecated(
+            level = DeprecationLevel.HIDDEN,
+            message = "Maintained for binary compatibility."
+        )
+        fun Saver(
+            skipPartiallyExpanded: Boolean,
+            confirmValueChange: (SheetValue) -> Boolean,
+            density: Density,
+            skipHiddenState: Boolean,
+        ) =
+            Saver(
+                skipPartiallyExpanded = skipPartiallyExpanded,
+                confirmValueChange = confirmValueChange,
+                skipHiddenState = skipHiddenState,
+                positionalThreshold = {
+                    with(density) { BottomSheetDefaults.PositionalThreshold.toPx() }
+                },
+                velocityThreshold = {
+                    with(density) { BottomSheetDefaults.VelocityThreshold.toPx() }
+                }
+            )
     }
+
+    @Deprecated(level = DeprecationLevel.HIDDEN, message = "Maintained for binary compatibility.")
+    constructor(
+        skipPartiallyExpanded: Boolean,
+        density: Density,
+        initialValue: SheetValue = Hidden,
+        confirmValueChange: (SheetValue) -> Boolean = { true },
+        skipHiddenState: Boolean = false,
+    ) : this(
+        skipPartiallyExpanded = skipPartiallyExpanded,
+        positionalThreshold = { with(density) { BottomSheetDefaults.PositionalThreshold.toPx() } },
+        velocityThreshold = { with(density) { BottomSheetDefaults.VelocityThreshold.toPx() } },
+        initialValue = initialValue,
+        confirmValueChange = confirmValueChange,
+        skipHiddenState = skipHiddenState,
+    )
 }
 
 /** Possible values of [SheetState]. */
@@ -350,6 +399,10 @@
     val windowInsets: WindowInsets
         @Composable get() = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom)
 
+    internal val PositionalThreshold = 56.dp
+
+    internal val VelocityThreshold = 125.dp
+
     /** The optional visual marker placed on top of a bottom sheet to indicate it may be dragged. */
     @Composable
     fun DragHandle(
@@ -439,8 +492,12 @@
     confirmValueChange: (SheetValue) -> Boolean = { true },
     initialValue: SheetValue = Hidden,
     skipHiddenState: Boolean = false,
+    positionalThreshold: Dp = BottomSheetDefaults.PositionalThreshold,
+    velocityThreshold: Dp = BottomSheetDefaults.VelocityThreshold,
 ): SheetState {
     val density = LocalDensity.current
+    val positionalThresholdToPx = { with(density) { positionalThreshold.toPx() } }
+    val velocityThresholdToPx = { with(density) { velocityThreshold.toPx() } }
     return rememberSaveable(
         skipPartiallyExpanded,
         confirmValueChange,
@@ -448,14 +505,16 @@
         saver =
             SheetState.Saver(
                 skipPartiallyExpanded = skipPartiallyExpanded,
+                positionalThreshold = positionalThresholdToPx,
+                velocityThreshold = velocityThresholdToPx,
                 confirmValueChange = confirmValueChange,
-                density = density,
                 skipHiddenState = skipHiddenState,
             )
     ) {
         SheetState(
             skipPartiallyExpanded,
-            density,
+            positionalThresholdToPx,
+            velocityThresholdToPx,
             initialValue,
             confirmValueChange,
             skipHiddenState,
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
index c345413..0784a16 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
@@ -374,6 +374,12 @@
      *
      * @param spacingBetweenTooltipAndAnchor the spacing between the tooltip and the anchor content.
      */
+    @Deprecated(
+        "Deprecated in favor of rememberTooltipPositionProvider API.",
+        replaceWith =
+            ReplaceWith("rememberTooltipPositionProvider(spacingBetweenTooltipAndAnchor)"),
+        level = DeprecationLevel.HIDDEN
+    )
     @Composable
     fun rememberPlainTooltipPositionProvider(
         spacingBetweenTooltipAndAnchor: Dp = SpacingBetweenTooltipAndAnchor
@@ -407,6 +413,12 @@
      *
      * @param spacingBetweenTooltipAndAnchor the spacing between the tooltip and the anchor content.
      */
+    @Deprecated(
+        "Deprecated in favor of rememberTooltipPositionProvider API.",
+        replaceWith =
+            ReplaceWith("rememberTooltipPositionProvider(spacingBetweenTooltipAndAnchor)"),
+        level = DeprecationLevel.HIDDEN
+    )
     @Composable
     fun rememberRichTooltipPositionProvider(
         spacingBetweenTooltipAndAnchor: Dp = SpacingBetweenTooltipAndAnchor
@@ -443,6 +455,53 @@
             }
         }
     }
+
+    /**
+     * [PopupPositionProvider] that should be used with either [RichTooltip] or [PlainTooltip]. It
+     * correctly positions the tooltip in respect to the anchor content.
+     *
+     * @param spacingBetweenTooltipAndAnchor the spacing between the tooltip and the anchor content.
+     */
+    @Composable
+    fun rememberTooltipPositionProvider(
+        spacingBetweenTooltipAndAnchor: Dp = SpacingBetweenTooltipAndAnchor
+    ): PopupPositionProvider {
+        val tooltipAnchorSpacing =
+            with(LocalDensity.current) { spacingBetweenTooltipAndAnchor.roundToPx() }
+        return remember(tooltipAnchorSpacing) {
+            object : PopupPositionProvider {
+                override fun calculatePosition(
+                    anchorBounds: IntRect,
+                    windowSize: IntSize,
+                    layoutDirection: LayoutDirection,
+                    popupContentSize: IntSize
+                ): IntOffset {
+                    // Horizontal alignment preference: middle -> start -> end
+                    // Vertical preference: above -> below
+
+                    // Tooltip prefers to be center aligned horizontally.
+                    var x = anchorBounds.left + (anchorBounds.width - popupContentSize.width) / 2
+
+                    if (x < 0) {
+                        // Make tooltip start aligned if colliding with the
+                        // left side of the screen
+                        x = anchorBounds.left
+                    } else if (x + popupContentSize.width > windowSize.width) {
+                        // Make tooltip end aligned if colliding with the
+                        // right side of the screen
+                        x = anchorBounds.right - popupContentSize.width
+                    }
+
+                    // Tooltip prefers to be above the anchor,
+                    // but if this causes the tooltip to overlap with the anchor
+                    // then we place it below the anchor
+                    var y = anchorBounds.top - popupContentSize.height - tooltipAnchorSpacing
+                    if (y < 0) y = anchorBounds.bottom + tooltipAnchorSpacing
+                    return IntOffset(x, y)
+                }
+            }
+        }
+    }
 }
 
 @Stable
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
index 70fea23..3debdfc 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
@@ -30,7 +30,6 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.requiredSizeIn
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.progressSemantics
 import androidx.compose.material3.internal.IncreaseVerticalSemanticsBounds
@@ -185,7 +184,6 @@
             .semantics(mergeDescendants = true) {
                 progressBarRangeInfo = ProgressBarRangeInfo(coercedProgress(), 0f..1f)
             }
-            .requiredSizeIn(minWidth = LinearContainerMinWidth)
             .size(
                 width = WavyProgressIndicatorDefaults.LinearContainerWidth,
                 height = WavyProgressIndicatorDefaults.LinearContainerHeight
@@ -373,7 +371,6 @@
         modifier
             .then(IncreaseVerticalSemanticsBounds)
             .progressSemantics()
-            .requiredSizeIn(minWidth = LinearContainerMinWidth)
             .size(
                 WavyProgressIndicatorDefaults.LinearContainerWidth,
                 WavyProgressIndicatorDefaults.LinearContainerHeight
diff --git a/compose/runtime/runtime-test-utils/build.gradle b/compose/runtime/runtime-test-utils/build.gradle
index f5ee280..f9f82e1 100644
--- a/compose/runtime/runtime-test-utils/build.gradle
+++ b/compose/runtime/runtime-test-utils/build.gradle
@@ -19,12 +19,21 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.runtime.testutils"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -73,6 +82,3 @@
     description = "Compose runtime test utils shared between runtime and compiler tests."
 }
 
-android {
-    namespace "androidx.compose.runtime.testutils"
-}
diff --git a/compose/runtime/runtime/integration-tests/build.gradle b/compose/runtime/runtime/integration-tests/build.gradle
index 233a8eb..791773c 100644
--- a/compose/runtime/runtime/integration-tests/build.gradle
+++ b/compose/runtime/runtime/integration-tests/build.gradle
@@ -25,12 +25,24 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.runtime.integrationtests"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
 
     sourceSets {
         commonMain {
@@ -92,10 +104,6 @@
     }
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.runtime.integrationtests"
-}
 
 tasks.withType(KotlinCompile).configureEach {
     kotlinOptions {
@@ -109,7 +117,7 @@
 }
 
 public File findFile() {
-    project.file("src/androidAndroidTest/kotlin/androidx/compose/runtime/GroupSizeTests.kt")
+    project.file("src/androidInstrumentedTest/kotlin/androidx/compose/runtime/GroupSizeTests.kt")
 }
 
 class UpdateExpectedGroupSizes extends DefaultTask {
diff --git a/compose/ui/ui-geometry/build.gradle b/compose/ui/ui-geometry/build.gradle
index 552d9fb..b9b102b 100644
--- a/compose/ui/ui-geometry/build.gradle
+++ b/compose/ui/ui-geometry/build.gradle
@@ -28,13 +28,21 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
-
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.ui.geometry"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -103,6 +111,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    namespace "androidx.compose.ui.geometry"
-}
diff --git a/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt b/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
index 6b44f1b..57085cf 100644
--- a/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
+++ b/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
@@ -51,7 +51,6 @@
 import androidx.compose.ui.graphics.isLayerManagerInitialized
 import androidx.compose.ui.graphics.isLayerPersistenceEnabled
 import androidx.compose.ui.graphics.nativeCanvas
-import androidx.compose.ui.graphics.supportsV23RenderNode
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.graphics.toPixelMap
 import androidx.compose.ui.unit.Density
@@ -1872,15 +1871,6 @@
         )
     }
 
-    @Test
-    fun testGraphicsLayerV23Supported() {
-        assertTrue(supportsV23RenderNode("Samsung"))
-        assertTrue(supportsV23RenderNode("Pixel"))
-        assertFalse(supportsV23RenderNode("vivo"))
-        assertFalse(supportsV23RenderNode("VIVO"))
-        assertFalse(supportsV23RenderNode("viVO"))
-    }
-
     private class GraphicsContextHostDrawable(
         val graphicsContext: GraphicsContext,
         val block: DrawScope.(GraphicsContext) -> Unit
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt
index 9134ef7..ed2e9d0 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt
@@ -32,7 +32,6 @@
 import androidx.compose.ui.graphics.layer.LayerManager
 import androidx.compose.ui.graphics.layer.view.DrawChildContainer
 import androidx.compose.ui.graphics.layer.view.ViewLayerContainer
-import java.util.Locale
 
 /**
  * Create a new [GraphicsContext] with the provided [ViewGroup] to contain [View] based layers.
@@ -202,7 +201,7 @@
         }
 
     internal companion object {
-        var isRenderNodeCompatible: Boolean = supportsV23RenderNode(Build.MANUFACTURER)
+        var isRenderNodeCompatible: Boolean = true
 
         const val enableLayerPersistence = false
     }
@@ -218,10 +217,3 @@
 
 internal val isLayerPersistenceEnabled: Boolean
     get() = AndroidGraphicsContext.enableLayerPersistence
-
-internal fun supportsV23RenderNode(manufacturer: String): Boolean =
-    // See b/371012452. Some Android devices don't support the reflective stub implementation
-    // of RenderNode. More specifically the cast of android.graphics.Canvas to
-    // android.view.DisplayListCanvas fails when trying to draw the layer itself.
-    // In these cases we should fallback to using the View based layer implementation instead
-    !manufacturer.lowercase(Locale.ENGLISH).contains("vivo")
diff --git a/compose/ui/ui-tooling-data/build.gradle b/compose/ui/ui-tooling-data/build.gradle
index f3ac046..472e819 100644
--- a/compose/ui/ui-tooling-data/build.gradle
+++ b/compose/ui/ui-tooling-data/build.gradle
@@ -28,12 +28,24 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.ui.tooling.data"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+    }
     jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
@@ -111,7 +123,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    compileSdk 35
-    namespace "androidx.compose.ui.tooling.data"
-}
diff --git a/compose/ui/ui-tooling-preview/build.gradle b/compose/ui/ui-tooling-preview/build.gradle
index 8293248..2ea5618 100644
--- a/compose/ui/ui-tooling-preview/build.gradle
+++ b/compose/ui/ui-tooling-preview/build.gradle
@@ -27,11 +27,20 @@
 plugins {
     id("AndroidXPlugin")
     id("AndroidXComposePlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.ui.tooling.preview"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
@@ -93,6 +102,3 @@
     metalavaK2UastEnabled = false
 }
 
-android {
-    namespace "androidx.compose.ui.tooling.preview"
-}
diff --git a/compose/ui/ui-unit/build.gradle b/compose/ui/ui-unit/build.gradle
index 9cd6331..ce761f72 100644
--- a/compose/ui/ui-unit/build.gradle
+++ b/compose/ui/ui-unit/build.gradle
@@ -28,12 +28,27 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.ui.unit"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+        optimization {
+            it.consumerKeepRules.publish = true
+            it.consumerKeepRules.files.add(
+                    new File(project.projectDir, "proguard-rules.pro")
+            )
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -116,9 +131,3 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
-android {
-    namespace "androidx.compose.ui.unit"
-    buildTypes.configureEach {
-        consumerProguardFiles("proguard-rules.pro")
-    }
-}
diff --git a/compose/ui/ui-util/build.gradle b/compose/ui/ui-util/build.gradle
index b1788829..f6ee5c2 100644
--- a/compose/ui/ui-util/build.gradle
+++ b/compose/ui/ui-util/build.gradle
@@ -27,12 +27,27 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.compose.ui.util"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+        optimization {
+            it.consumerKeepRules.publish = true
+            it.consumerKeepRules.files.add(
+                    new File(project.projectDir, "proguard-rules.pro")
+            )
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -105,9 +120,3 @@
     composeCompilerPluginEnabled = false
 }
 
-android {
-    namespace "androidx.compose.ui.util"
-    buildTypes.configureEach {
-        consumerProguardFiles("proguard-rules.pro")
-    }
-}
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
index bb7966b..1173955 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
@@ -20,7 +20,6 @@
 
 import android.view.MotionEvent.ACTION_HOVER_ENTER
 import android.view.MotionEvent.ACTION_HOVER_EXIT
-import androidx.collection.IntObjectMap
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -63,7 +62,6 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontFamily
@@ -3419,9 +3417,6 @@
     override val focusOwner: FocusOwner
         get() = TODO("Not yet implemented")
 
-    override val semanticsOwner: SemanticsOwner
-        get() = TODO("Not yet implemented")
-
     override val windowInfo: WindowInfo
         get() = TODO("Not yet implemented")
 
@@ -3567,12 +3562,8 @@
     }
 
     override var measureIteration: Long = 0
-
     override val viewConfiguration: ViewConfiguration
         get() = TODO("Not yet implemented")
 
-    override val layoutNodes: IntObjectMap<LayoutNode>
-        get() = TODO("Not yet implemented")
-
     override val sharedDrawScope = LayoutNodeDrawScope()
 }
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
index 4c6c824..2552b929 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
@@ -21,8 +21,6 @@
 import android.view.InputDevice
 import android.view.KeyEvent as AndroidKeyEvent
 import android.view.MotionEvent
-import androidx.collection.IntObjectMap
-import androidx.collection.intObjectMapOf
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -59,8 +57,6 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.EmptySemanticsModifier
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontFamily
@@ -2851,9 +2847,6 @@
     override val rootForTest: RootForTest
         get() = TODO("Not yet implemented")
 
-    override val layoutNodes: IntObjectMap<LayoutNode>
-        get() = TODO("Not yet implemented")
-
     override val hapticFeedBack: HapticFeedback
         get() = TODO("Not yet implemented")
 
@@ -2914,9 +2907,6 @@
     override val focusOwner: FocusOwner
         get() = TODO("Not yet implemented")
 
-    override val semanticsOwner: SemanticsOwner =
-        SemanticsOwner(root, EmptySemanticsModifier(), intObjectMapOf())
-
     override val windowInfo: WindowInfo
         get() = TODO("Not yet implemented")
 
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
index 8295452..ca6ec66 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
@@ -18,8 +18,6 @@
 
 package androidx.compose.ui.layout
 
-import androidx.collection.IntObjectMap
-import androidx.collection.intObjectMapOf
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
 import androidx.compose.ui.autofill.Autofill
@@ -54,8 +52,6 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.EmptySemanticsModifier
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontFamily
@@ -165,12 +161,7 @@
 
     override fun onDetach(node: LayoutNode) {}
 
-    override val root: LayoutNode = LayoutNode()
-
-    override val semanticsOwner: SemanticsOwner =
-        SemanticsOwner(root, EmptySemanticsModifier(), intObjectMapOf())
-
-    override val layoutNodes: IntObjectMap<LayoutNode>
+    override val root: LayoutNode
         get() = TODO("Not yet implemented")
 
     override val sharedDrawScope: LayoutNodeDrawScope
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
index 56e499a..fd30536 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
@@ -18,8 +18,6 @@
 
 package androidx.compose.ui.node
 
-import androidx.collection.IntObjectMap
-import androidx.collection.intObjectMapOf
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -50,8 +48,6 @@
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
 import androidx.compose.ui.platform.invertTo
-import androidx.compose.ui.semantics.EmptySemanticsModifier
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontFamily
@@ -389,9 +385,6 @@
     override val density: Density
         get() = Density(1f)
 
-    override val layoutNodes: IntObjectMap<LayoutNode>
-        get() = TODO("Not yet implemented")
-
     override val layoutDirection: LayoutDirection
         get() = LayoutDirection.Ltr
 
@@ -428,9 +421,6 @@
     override val focusOwner: FocusOwner
         get() = TODO("Not yet implemented")
 
-    override val semanticsOwner: SemanticsOwner =
-        SemanticsOwner(root, EmptySemanticsModifier(), intObjectMapOf())
-
     override val windowInfo: WindowInfo
         get() = TODO("Not yet implemented")
 
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsInfoTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsInfoTest.kt
deleted file mode 100644
index 79bad61..0000000
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsInfoTest.kt
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2024 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.ui.semantics
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.node.RootForTest
-import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.semantics.SemanticsProperties.TestTag
-import androidx.compose.ui.test.junit4.ComposeContentTestRule
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import com.google.common.truth.Correspondence
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.Test
-import org.junit.Rule
-import org.junit.runner.RunWith
-
-@MediumTest
-@RunWith(AndroidJUnit4::class)
-class SemanticsInfoTest {
-
-    @get:Rule val rule = createComposeRule()
-
-    lateinit var semanticsOwner: SemanticsOwner
-
-    @Test
-    fun contentWithNoSemantics() {
-        // Arrange.
-        rule.setTestContent { Box {} }
-        rule.waitForIdle()
-
-        // Act.
-        val rootSemantics = semanticsOwner.rootInfo
-
-        // Assert.
-        assertThat(rootSemantics).isNotNull()
-        assertThat(rootSemantics.parentInfo).isNull()
-        assertThat(rootSemantics.childrenInfo.size).isEqualTo(1)
-
-        // Assert extension Functions.
-        assertThat(rootSemantics.findSemanticsParent()).isNull()
-        assertThat(rootSemantics.findMergingSemanticsParent()).isNull()
-        assertThat(rootSemantics.findSemanticsChildren()).isEmpty()
-    }
-
-    @Test
-    fun singleSemanticsModifier() {
-        // Arrange.
-        rule.setTestContent { Box(Modifier.semantics { this.testTag = "testTag" }) }
-        rule.waitForIdle()
-
-        // Act.
-        val rootSemantics = semanticsOwner.rootInfo
-        val semantics = rule.getSemanticsInfoForTag("testTag")!!
-
-        // Assert.
-        assertThat(rootSemantics.parentInfo).isNull()
-        assertThat(rootSemantics.childrenInfo.asMutableList()).containsExactly(semantics)
-
-        assertThat(semantics.parentInfo).isEqualTo(rootSemantics)
-        assertThat(semantics.childrenInfo.size).isEqualTo(0)
-
-        // Assert extension Functions.
-        assertThat(rootSemantics.findSemanticsParent()).isNull()
-        assertThat(rootSemantics.findMergingSemanticsParent()).isNull()
-        assertThat(rootSemantics.findSemanticsChildren().map { it.semanticsConfiguration })
-            .comparingElementsUsing(SemanticsConfigurationComparator)
-            .containsExactly(SemanticsConfiguration().apply { testTag = "testTag" })
-
-        assertThat(semantics.findSemanticsParent()).isEqualTo(rootSemantics)
-        assertThat(semantics.findMergingSemanticsParent()).isNull()
-        assertThat(semantics.findSemanticsChildren()).isEmpty()
-    }
-
-    @Test
-    fun twoSemanticsModifiers() {
-        // Arrange.
-        rule.setTestContent {
-            Box(Modifier.semantics { this.testTag = "item1" })
-            Box(Modifier.semantics { this.testTag = "item2" })
-        }
-        rule.waitForIdle()
-
-        // Act.
-        val rootSemantics: SemanticsInfo = semanticsOwner.rootInfo
-        val semantics1 = rule.getSemanticsInfoForTag("item1")
-        val semantics2 = rule.getSemanticsInfoForTag("item2")
-
-        // Assert.
-        assertThat(rootSemantics.parentInfo).isNull()
-        assertThat(rootSemantics.childrenInfo.map { it.semanticsConfiguration }.toList())
-            .comparingElementsUsing(SemanticsConfigurationComparator)
-            .containsExactly(
-                SemanticsConfiguration().apply { testTag = "item1" },
-                SemanticsConfiguration().apply { testTag = "item2" }
-            )
-            .inOrder()
-
-        assertThat(rootSemantics.findSemanticsChildren().map { it.semanticsConfiguration })
-            .comparingElementsUsing(SemanticsConfigurationComparator)
-            .containsExactly(
-                SemanticsConfiguration().apply { testTag = "item1" },
-                SemanticsConfiguration().apply { testTag = "item2" }
-            )
-            .inOrder()
-
-        checkNotNull(semantics1)
-        assertThat(semantics1.parentInfo).isEqualTo(rootSemantics)
-        assertThat(semantics1.childrenInfo.size).isEqualTo(0)
-
-        checkNotNull(semantics2)
-        assertThat(semantics2.parentInfo).isEqualTo(rootSemantics)
-        assertThat(semantics2.childrenInfo.size).isEqualTo(0)
-
-        // Assert extension Functions.
-        assertThat(rootSemantics.findSemanticsParent()).isNull()
-        assertThat(rootSemantics.findMergingSemanticsParent()).isNull()
-        assertThat(rootSemantics.findSemanticsChildren().map { it.semanticsConfiguration })
-            .comparingElementsUsing(SemanticsConfigurationComparator)
-            .containsExactly(
-                SemanticsConfiguration().apply { testTag = "item1" },
-                SemanticsConfiguration().apply { testTag = "item2" }
-            )
-            .inOrder()
-
-        assertThat(semantics1.findSemanticsParent()).isEqualTo(rootSemantics)
-        assertThat(semantics1.findMergingSemanticsParent()).isNull()
-        assertThat(semantics1.findSemanticsChildren()).isEmpty()
-
-        assertThat(semantics2.findSemanticsParent()).isEqualTo(rootSemantics)
-        assertThat(semantics2.findMergingSemanticsParent()).isNull()
-        assertThat(semantics2.findSemanticsChildren()).isEmpty()
-    }
-
-    // TODO(ralu): Split this into multiple tests.
-    @Test
-    fun nodeDeepInHierarchy() {
-        // Arrange.
-        rule.setTestContent {
-            Column(Modifier.semantics(mergeDescendants = true) { testTag = "outerColumn" }) {
-                Row(Modifier.semantics { testTag = "outerRow" }) {
-                    Column(Modifier.semantics(mergeDescendants = true) { testTag = "column" }) {
-                        Row(Modifier.semantics { testTag = "row" }) {
-                            Column {
-                                Box(Modifier.semantics { testTag = "box" })
-                                Row(
-                                    Modifier.semantics {}
-                                        .semantics { testTag = "testTarget" }
-                                        .semantics { testTag = "extra modifier2" }
-                                ) {
-                                    Box { Box(Modifier.semantics { testTag = "child1" }) }
-                                    Box(Modifier.semantics { testTag = "child2" }) {
-                                        Box(Modifier.semantics { testTag = "grandChild" })
-                                    }
-                                    Box {}
-                                    Row {
-                                        Box {}
-                                        Box {}
-                                    }
-                                    Box { Box(Modifier.semantics { testTag = "child3" }) }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        rule.waitForIdle()
-        val row = rule.getSemanticsInfoForTag(tag = "row", useUnmergedTree = true)
-        val column = rule.getSemanticsInfoForTag("column")
-
-        // Act.
-        val testTarget = rule.getSemanticsInfoForTag(tag = "testTarget", useUnmergedTree = true)
-
-        // Assert.
-        checkNotNull(testTarget)
-        assertThat(testTarget.parentInfo).isNotEqualTo(row)
-        assertThat(testTarget.findSemanticsParent()).isEqualTo(row)
-        assertThat(testTarget.findMergingSemanticsParent()).isEqualTo(column)
-        assertThat(testTarget.childrenInfo.size).isEqualTo(5)
-        assertThat(testTarget.findSemanticsChildren().map { it.semanticsConfiguration })
-            .comparingElementsUsing(SemanticsConfigurationComparator)
-            .containsExactly(
-                SemanticsConfiguration().apply { testTag = "child1" },
-                SemanticsConfiguration().apply { testTag = "child2" },
-                SemanticsConfiguration().apply { testTag = "child3" }
-            )
-            .inOrder()
-        assertThat(testTarget.semanticsConfiguration?.getOrNull(TestTag)).isEqualTo("testTarget")
-    }
-
-    private fun ComposeContentTestRule.setTestContent(composable: @Composable () -> Unit) {
-        setContent {
-            semanticsOwner = (LocalView.current as RootForTest).semanticsOwner
-            composable()
-        }
-    }
-
-    /** Helper function that returns a list of children that is easier to assert on in tests. */
-    private fun SemanticsInfo.findSemanticsChildren(): List<SemanticsInfo> {
-        val children = mutableListOf<SemanticsInfo>()
-        [email protected] { children.add(it) }
-        return children
-    }
-
-    private fun ComposeContentTestRule.getSemanticsInfoForTag(
-        tag: String,
-        useUnmergedTree: Boolean = true
-    ): SemanticsInfo? {
-        return semanticsOwner[onNodeWithTag(tag, useUnmergedTree).semanticsId()]
-    }
-
-    companion object {
-        private val SemanticsConfigurationComparator =
-            Correspondence.from<SemanticsConfiguration, SemanticsConfiguration>(
-                { actual, expected ->
-                    actual != null &&
-                        expected != null &&
-                        actual.getOrNull(TestTag) == expected.getOrNull(TestTag)
-                },
-                "has same test tag as "
-            )
-    }
-}
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsListenerTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsListenerTest.kt
deleted file mode 100644
index 77965fe..0000000
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsListenerTest.kt
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright 2024 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.ui.semantics
-
-import androidx.compose.foundation.border
-import androidx.compose.foundation.focusable
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.size
-import androidx.compose.material.Text
-import androidx.compose.material.TextField
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.ComposeUiFlags
-import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.isExactly
-import androidx.compose.ui.focus.onFocusChanged
-import androidx.compose.ui.graphics.Color.Companion.Black
-import androidx.compose.ui.graphics.Color.Companion.Red
-import androidx.compose.ui.node.RootForTest
-import androidx.compose.ui.node.SemanticsModifierNode
-import androidx.compose.ui.node.invalidateSemantics
-import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.SemanticsNodeInteraction
-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.requestFocus
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastJoinToString
-import androidx.test.filters.MediumTest
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.Test
-import org.junit.Before
-import org.junit.Rule
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@MediumTest
-@RunWith(Parameterized::class)
-class SemanticsListenerTest(private val isSemanticAutofillEnabled: Boolean) {
-
-    @get:Rule val rule = createComposeRule()
-
-    private lateinit var semanticsOwner: SemanticsOwner
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "isSemanticAutofillEnabled = {0}")
-        fun initParameters() = listOf(false, true)
-    }
-
-    @Before
-    fun setup() {
-        @OptIn(ExperimentalComposeUiApi::class)
-        ComposeUiFlags.isSemanticAutofillEnabled = isSemanticAutofillEnabled
-    }
-
-    // Initial layout does not trigger listeners. Users have to detect the initial semantics
-    //  values by detecting first layout (You can get the bounds from RectManager.RectList).
-    @Test
-    fun initialComposition_doesNotTriggerListeners() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Text(text = "text")
-        }
-
-        // Assert.
-        rule.runOnIdle { assertThat(events).isEmpty() }
-    }
-
-    @Test
-    fun addingNonSemanticsModifier() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var addModifier by mutableStateOf(false)
-        val text = AnnotatedString("text")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(
-                modifier =
-                    Modifier.then(if (addModifier) Modifier.size(1000.dp) else Modifier)
-                        .semantics { this.text = text }
-                        .testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle { addModifier = true }
-
-        // Assert.
-        rule.runOnIdle { assertThat(events).isEmpty() }
-    }
-
-    @Test
-    fun removingNonSemanticsModifier() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var removeModifier by mutableStateOf(false)
-        val text = AnnotatedString("text")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(
-                modifier =
-                    Modifier.then(if (removeModifier) Modifier else Modifier.size(1000.dp))
-                        .semantics { this.text = text }
-                        .testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle { removeModifier = true }
-
-        // Assert.
-        rule.runOnIdle { assertThat(events).isEmpty() }
-    }
-
-    @Test
-    fun addingSemanticsModifier() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var addModifier by mutableStateOf(false)
-        val text = AnnotatedString("text")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(
-                modifier =
-                    Modifier.size(100.dp)
-                        .then(
-                            if (addModifier) Modifier.semantics { this.text = text } else Modifier
-                        )
-                        .testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle { addModifier = true }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = null, newSemantics = "text"))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun removingSemanticsModifier() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var removeModifier by mutableStateOf(false)
-        val text = AnnotatedString("text")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(
-                modifier =
-                    Modifier.size(1000.dp)
-                        .then(
-                            if (removeModifier) Modifier
-                            else Modifier.semantics { this.text = text }
-                        )
-                        .testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle { removeModifier = true }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = "text", newSemantics = null))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun changingMutableSemanticsProperty() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var text by mutableStateOf(AnnotatedString("text1"))
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(modifier = Modifier.semantics { this.text = text }.testTag("item"))
-        }
-
-        // Act.
-        rule.runOnIdle { text = AnnotatedString("text2") }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = "text1", newSemantics = "text2"))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun changingMutableSemanticsProperty_alongWithRecomposition() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var text by mutableStateOf(AnnotatedString("text1"))
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(
-                modifier =
-                    Modifier.border(2.dp, if (text.text == "text1") Red else Black)
-                        .semantics { this.text = text }
-                        .testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle { text = AnnotatedString("text2") }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = "text1", newSemantics = "text2"))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun changingSemanticsProperty_andCallingInvalidateSemantics() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        val modifierNode =
-            object : SemanticsModifierNode, Modifier.Node() {
-                override fun SemanticsPropertyReceiver.applySemantics() {}
-            }
-        var text = AnnotatedString("text1")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Box(
-                modifier =
-                    Modifier.elementFor(modifierNode).semantics { this.text = text }.testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle {
-            text = AnnotatedString("text2")
-            modifierNode.invalidateSemantics()
-        }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = "text1", newSemantics = "text2"))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun textChange() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var text by mutableStateOf("text1")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Text(text = text, modifier = Modifier.testTag("item"))
-        }
-
-        // Act.
-        rule.runOnIdle { text = "text2" }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = "text1", newSemantics = "text2"))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun multipleTextChanges() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var text by mutableStateOf("text1")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(Event(info.semanticsId, prev?.Text, info.semanticsConfiguration?.Text))
-            }
-        ) {
-            Text(text = text, modifier = Modifier.testTag("item"))
-        }
-
-        // Act.
-        rule.runOnIdle { text = "text2" }
-        rule.runOnIdle { text = "text3" }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(
-                        Event(semanticsId, prevSemantics = "text1", newSemantics = "text2"),
-                        Event(semanticsId, prevSemantics = "text2", newSemantics = "text3")
-                    )
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun EditTextChange() {
-        // Arrange.
-        val events = mutableListOf<Event<String>>()
-        var text by mutableStateOf("text1")
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(
-                    Event(
-                        info.semanticsId,
-                        prev?.EditableText,
-                        info.semanticsConfiguration?.EditableText
-                    )
-                )
-            }
-        ) {
-            TextField(
-                value = text,
-                onValueChange = { text = it },
-                modifier = Modifier.testTag("item")
-            )
-        }
-
-        // Act.
-        rule.runOnIdle { text = "text2" }
-
-        // Assert.
-        val semanticsId = rule.onNodeWithTag("item").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(Event(semanticsId, prevSemantics = "text1", newSemantics = "text2"))
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun FocusChange_withNoRecomposition() {
-        // Arrange.
-        val events = mutableListOf<Event<Boolean>>()
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(
-                    Event(
-                        info.semanticsId,
-                        prev?.getOrNull(SemanticsProperties.Focused),
-                        info.semanticsConfiguration?.getOrNull(SemanticsProperties.Focused)
-                    )
-                )
-            }
-        ) {
-            Column {
-                Box(Modifier.testTag("item1").size(100.dp).focusable())
-                Box(Modifier.testTag("item2").size(100.dp).focusable())
-            }
-        }
-        rule.onNodeWithTag("item1").requestFocus()
-        rule.runOnIdle { events.clear() }
-
-        // Act.
-        rule.onNodeWithTag("item2").requestFocus()
-
-        // Assert.
-        val item1 = rule.onNodeWithTag("item1").semanticsId
-        val item2 = rule.onNodeWithTag("item2").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(
-                        Event(item1, prevSemantics = true, newSemantics = false),
-                        Event(item2, prevSemantics = false, newSemantics = true)
-                    )
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    @Test
-    fun FocusChange_thatCausesRecomposition() {
-        // Arrange.
-        val events = mutableListOf<Event<Boolean>>()
-        rule.setTestContent(
-            onSemanticsChange = { info, prev ->
-                events.add(
-                    Event(
-                        info.semanticsId,
-                        prev?.getOrNull(SemanticsProperties.Focused),
-                        info.semanticsConfiguration?.getOrNull(SemanticsProperties.Focused)
-                    )
-                )
-            }
-        ) {
-            Column {
-                FocusableBox(Modifier.testTag("item1"))
-                FocusableBox(Modifier.testTag("item2"))
-            }
-        }
-        rule.onNodeWithTag("item1").requestFocus()
-        rule.runOnIdle { events.clear() }
-
-        // Act.
-        rule.onNodeWithTag("item2").requestFocus()
-
-        // Assert.
-        val item1 = rule.onNodeWithTag("item1").semanticsId
-        val item2 = rule.onNodeWithTag("item2").semanticsId
-        rule.runOnIdle {
-            if (isSemanticAutofillEnabled) {
-                assertThat(events)
-                    .isExactly(
-                        Event(item1, prevSemantics = true, newSemantics = false),
-                        Event(item2, prevSemantics = false, newSemantics = true)
-                    )
-            } else {
-                assertThat(events).isEmpty()
-            }
-        }
-    }
-
-    private val SemanticsConfiguration.Text
-        get() = getOrNull(SemanticsProperties.Text)?.fastJoinToString()
-
-    private val SemanticsConfiguration.EditableText
-        get() = getOrNull(SemanticsProperties.EditableText)?.toString()
-
-    private fun ComposeContentTestRule.setTestContent(
-        onSemanticsChange: (SemanticsInfo, SemanticsConfiguration?) -> Unit,
-        composable: @Composable () -> Unit
-    ) {
-        val semanticsListener =
-            object : SemanticsListener {
-                override fun onSemanticsChanged(
-                    semanticsInfo: SemanticsInfo,
-                    previousSemanticsConfiguration: SemanticsConfiguration?
-                ) {
-                    onSemanticsChange(semanticsInfo, previousSemanticsConfiguration)
-                }
-            }
-        setContent {
-            semanticsOwner = (LocalView.current as RootForTest).semanticsOwner
-            DisposableEffect(semanticsOwner) {
-                semanticsOwner.listeners.add(semanticsListener)
-                onDispose { semanticsOwner.listeners.remove(semanticsListener) }
-            }
-            composable()
-        }
-    }
-
-    data class Event<T>(val semanticsId: Int, val prevSemantics: T?, val newSemantics: T?)
-
-    // TODO(b/272068594): Add api to fetch the semantics id from SemanticsNodeInteraction directly.
-    private val SemanticsNodeInteraction.semanticsId: Int
-        get() = fetchSemanticsNode().id
-
-    @Composable
-    private fun FocusableBox(
-        modifier: Modifier = Modifier,
-        content: @Composable BoxScope.() -> Unit = {}
-    ) {
-        var borderColor by remember { mutableStateOf(Black) }
-        Box(
-            modifier =
-                modifier
-                    .size(100.dp)
-                    .onFocusChanged { borderColor = if (it.isFocused) Red else Black }
-                    .border(2.dp, borderColor)
-                    .focusable(),
-            content = content
-        )
-    }
-}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
index b86440d..ff82cbf 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
@@ -298,8 +298,6 @@
                     SemanticsContentDataType
                 )
         }
-    // TODO(b/138549623): Instead of creating a flattened tree by using the nodes from the map, we
-    //  can use SemanticsOwner to get the root SemanticsInfo and create a more representative tree.
     var index = AutofillApi26Helper.addChildCount(root, count)
 
     // Iterate through currentSemanticsNodes, finding autofill-related nodes
@@ -479,7 +477,7 @@
 }
 
 @RequiresApi(Build.VERSION_CODES.O)
-private class AutofillManagerWrapperImpl(val view: View) : AutofillManagerWrapper {
+private class AutofillManagerWrapperImpl(val view: AndroidComposeView) : AutofillManagerWrapper {
     override val autofillManager =
         view.context.getSystemService(PlatformAndroidManager::class.java)
             ?: error("Autofill service could not be located.")
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index 7dc9d64..dfac967 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -63,8 +63,6 @@
 import androidx.annotation.DoNotInline
 import androidx.annotation.RequiresApi
 import androidx.annotation.VisibleForTesting
-import androidx.collection.MutableIntObjectMap
-import androidx.collection.mutableIntObjectMapOf
 import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
@@ -431,12 +429,9 @@
                     .then(dragAndDropManager.modifier)
         }
 
-    override val layoutNodes: MutableIntObjectMap<LayoutNode> = mutableIntObjectMapOf()
-
     override val rootForTest: RootForTest = this
 
-    override val semanticsOwner: SemanticsOwner =
-        SemanticsOwner(root, rootSemanticsNode, layoutNodes)
+    override val semanticsOwner: SemanticsOwner = SemanticsOwner(root, rootSemanticsNode)
     private val composeAccessibilityDelegate = AndroidComposeViewAccessibilityDelegateCompat(this)
     internal var contentCaptureManager =
         AndroidContentCaptureManager(
@@ -1031,12 +1026,9 @@
         composeAccessibilityDelegate.SendRecurringAccessibilityEventsIntervalMillis = intervalMillis
     }
 
-    override fun onAttach(node: LayoutNode) {
-        layoutNodes[node.semanticsId] = node
-    }
+    override fun onAttach(node: LayoutNode) {}
 
     override fun onDetach(node: LayoutNode) {
-        layoutNodes.remove(node.semanticsId)
         measureAndLayoutDelegate.onNodeDetached(node)
         requestClearInvalidObservations()
         @OptIn(ExperimentalComposeUiApi::class)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
index 7deeca8..7036817 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
@@ -2355,11 +2355,11 @@
             if (layoutNode.nodes.has(Nodes.Semantics)) layoutNode
             else layoutNode.findClosestParentNode { it.nodes.has(Nodes.Semantics) }
 
-        val config = semanticsNode?.semanticsConfiguration ?: return
+        val config = semanticsNode?.collapsedSemantics ?: return
         if (!config.isMergingSemanticsOfDescendants) {
             semanticsNode
                 .findClosestParentNode {
-                    it.semanticsConfiguration?.isMergingSemanticsOfDescendants == true
+                    it.collapsedSemantics?.isMergingSemanticsOfDescendants == true
                 }
                 ?.let { semanticsNode = it }
         }
@@ -3264,12 +3264,12 @@
     val ancestor =
         layoutNode.findClosestParentNode {
             // looking for text field merging node
-            val ancestorSemanticsConfiguration = it.semanticsConfiguration
+            val ancestorSemanticsConfiguration = it.collapsedSemantics
             ancestorSemanticsConfiguration?.isMergingSemanticsOfDescendants == true &&
                 ancestorSemanticsConfiguration.contains(SemanticsProperties.EditableText)
         }
     return ancestor != null &&
-        ancestor.semanticsConfiguration?.getOrNull(SemanticsProperties.Focused) != true
+        ancestor.collapsedSemantics?.getOrNull(SemanticsProperties.Focused) != true
 }
 
 private fun AccessibilityAction<*>.accessibilityEquals(other: Any?): Boolean {
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
index d2ab361..0b66d5d 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
@@ -60,6 +60,7 @@
     init {
         clipChildren = false
         clipToPadding = false
+        importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES
     }
 
     /**
diff --git a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index c884b74..1f96189 100644
--- a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -17,8 +17,6 @@
 
 package androidx.compose.ui.node
 
-import androidx.collection.IntObjectMap
-import androidx.collection.intObjectMapOf
 import androidx.compose.testutils.TestViewConfiguration
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
@@ -68,10 +66,8 @@
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
 import androidx.compose.ui.platform.invertTo
-import androidx.compose.ui.semantics.EmptySemanticsModifier
 import androidx.compose.ui.semantics.SemanticsConfiguration
 import androidx.compose.ui.semantics.SemanticsModifier
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.semantics.SemanticsPropertyReceiver
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
@@ -2318,8 +2314,6 @@
 internal class MockOwner(
     private val position: IntOffset = IntOffset.Zero,
     override val root: LayoutNode = LayoutNode(),
-    override val semanticsOwner: SemanticsOwner =
-        SemanticsOwner(root, EmptySemanticsModifier(), intObjectMapOf()),
     override val coroutineContext: CoroutineContext =
         Executors.newFixedThreadPool(3).asCoroutineDispatcher()
 ) : Owner {
@@ -2553,9 +2547,6 @@
     override val viewConfiguration: ViewConfiguration
         get() = TODO("Not yet implemented")
 
-    override val layoutNodes: IntObjectMap<LayoutNode>
-        get() = TODO("Not yet implemented")
-
     override val sharedDrawScope = LayoutNodeDrawScope()
 }
 
diff --git a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
index bc17a55..8c77a83 100644
--- a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
+++ b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
@@ -18,8 +18,6 @@
 
 package androidx.compose.ui.node
 
-import androidx.collection.IntObjectMap
-import androidx.collection.intObjectMapOf
 import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -52,8 +50,6 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.EmptySemanticsModifier
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontFamily
@@ -337,9 +333,7 @@
 
         override fun onDetach(node: LayoutNode) {}
 
-        override val root: LayoutNode = LayoutNode()
-
-        override val layoutNodes: IntObjectMap<LayoutNode>
+        override val root: LayoutNode
             get() = TODO("Not yet implemented")
 
         override val sharedDrawScope: LayoutNodeDrawScope
@@ -381,9 +375,6 @@
         override val focusOwner: FocusOwner
             get() = TODO("Not yet implemented")
 
-        override val semanticsOwner: SemanticsOwner =
-            SemanticsOwner(root, EmptySemanticsModifier(), intObjectMapOf())
-
         override val windowInfo: WindowInfo
             get() = TODO("Not yet implemented")
 
@@ -451,7 +442,7 @@
         override fun forceMeasureTheSubtree(layoutNode: LayoutNode, affectsLookahead: Boolean) =
             TODO("Not yet implemented")
 
-        override fun onSemanticsChange() {}
+        override fun onSemanticsChange() = TODO("Not yet implemented")
 
         override fun onLayoutChange(layoutNode: LayoutNode) = TODO("Not yet implemented")
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index ace8eed..2da7de0 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -19,8 +19,6 @@
 import androidx.compose.runtime.CompositionLocalMap
 import androidx.compose.runtime.collection.MutableVector
 import androidx.compose.runtime.collection.mutableVectorOf
-import androidx.compose.ui.ComposeUiFlags
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
@@ -56,7 +54,6 @@
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.simpleIdentityToString
 import androidx.compose.ui.semantics.SemanticsConfiguration
-import androidx.compose.ui.semantics.SemanticsInfo
 import androidx.compose.ui.semantics.generateSemanticsId
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Density
@@ -91,7 +88,6 @@
     Remeasurement,
     OwnerScope,
     LayoutInfo,
-    SemanticsInfo,
     ComposeUiNode,
     InteroperableComposeUiNode,
     Owner.OnLayoutCompletedListener {
@@ -398,62 +394,43 @@
         invalidateMeasurements()
     }
 
-    private var _semanticsConfiguration: SemanticsConfiguration? = null
-    override val semanticsConfiguration: SemanticsConfiguration?
-        get() {
-            // This is needed until we completely move to the new world where we always pre-compute
-            // the semantics configuration. At that point, this can be replaced by
-            // check(!isSemanticsInvalidated) or remove this custom getter.
-            if (isSemanticsInvalidated) {
-                _semanticsConfiguration = calculateSemanticsConfiguration()
-            }
-            return _semanticsConfiguration
-        }
-
-    private fun calculateSemanticsConfiguration(): SemanticsConfiguration? {
-        if (!nodes.has(Nodes.Semantics)) return null
-
-        var config = SemanticsConfiguration()
-        requireOwner().snapshotObserver.observeSemanticsReads(this) {
-            nodes.tailToHead(Nodes.Semantics) {
-                if (it.shouldClearDescendantSemantics) {
-                    config = SemanticsConfiguration()
-                    config.isClearingSemantics = true
-                }
-                if (it.shouldMergeDescendantSemantics) {
-                    config.isMergingSemanticsOfDescendants = true
-                }
-                with(config) { with(it) { applySemantics() } }
-            }
-        }
-        return config
-    }
-
-    private var isSemanticsInvalidated = false
+    private var _collapsedSemantics: SemanticsConfiguration? = null
 
     internal fun invalidateSemantics() {
-        if (
-            @OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isSemanticAutofillEnabled ||
-                nodes.isUpdating ||
-                applyingModifierOnAttach
-        ) {
-            // We are currently updating the modifier, so just schedule an invalidation. After
-            // applying the modifier, we will notify listeners of semantics changes.
-            isSemanticsInvalidated = true
-        } else {
-            // We are not currently updating the modifier, so instead of scheduling invalidation,
-            // we update the semantics configuration and send the notification event right away.
-            val prev = _semanticsConfiguration
-            _semanticsConfiguration = calculateSemanticsConfiguration()
-            requireOwner().semanticsOwner.notifySemanticsChange(this, prev)
-        }
-
+        _collapsedSemantics = null
         // TODO(lmr): this ends up scheduling work that diffs the entire tree, but we should
         //  eventually move to marking just this node as invalidated since we are invalidating
         //  on a per-node level. This should preserve current behavior for now.
         requireOwner().onSemanticsChange()
     }
 
+    internal val collapsedSemantics: SemanticsConfiguration?
+        get() {
+            // TODO: investigate if there's a better way to approach "half attached" state and
+            // whether or not deactivated nodes should be considered removed or not.
+            if (!isAttached || isDeactivated) return null
+
+            if (!nodes.has(Nodes.Semantics) || _collapsedSemantics != null) {
+                return _collapsedSemantics
+            }
+
+            var config = SemanticsConfiguration()
+            requireOwner().snapshotObserver.observeSemanticsReads(this) {
+                nodes.tailToHead(Nodes.Semantics) {
+                    if (it.shouldClearDescendantSemantics) {
+                        config = SemanticsConfiguration()
+                        config.isClearingSemantics = true
+                    }
+                    if (it.shouldMergeDescendantSemantics) {
+                        config.isMergingSemanticsOfDescendants = true
+                    }
+                    with(config) { with(it) { applySemantics() } }
+                }
+            }
+            _collapsedSemantics = config
+            return config
+        }
+
     /**
      * Set the [Owner] of this LayoutNode. This LayoutNode must not already be attached. [owner]
      * must match its [parent].[owner].
@@ -486,7 +463,9 @@
         pendingModifier?.let { applyModifier(it) }
         pendingModifier = null
 
-        if (nodes.has(Nodes.Semantics)) invalidateSemantics()
+        if (nodes.has(Nodes.Semantics)) {
+            invalidateSemantics()
+        }
         owner.onAttach(this)
 
         // Update lookahead root when attached. For nested cases, we'll always use the
@@ -538,9 +517,9 @@
         }
         layoutDelegate.resetAlignmentLines()
         onDetach?.invoke(owner)
+
         if (nodes.has(Nodes.Semantics)) {
-            _semanticsConfiguration = null
-            requireOwner().onSemanticsChange()
+            invalidateSemantics()
         }
         nodes.runDetachLifecycle()
         ignoreRemeasureRequests { _foldedChildren.forEach { child -> child.detach() } }
@@ -576,10 +555,6 @@
             return _zSortedChildren
         }
 
-    @Suppress("UNCHECKED_CAST")
-    override val childrenInfo: MutableVector<SemanticsInfo>
-        get() = zSortedChildren as MutableVector<SemanticsInfo>
-
     override val isValidOwnerScope: Boolean
         get() = isAttached
 
@@ -891,14 +866,6 @@
         if (lookaheadRoot == null && nodes.has(Nodes.ApproachMeasure)) {
             lookaheadRoot = this
         }
-        // Notify semantics listeners if semantics was invalidated.
-        @OptIn(ExperimentalComposeUiApi::class)
-        if (ComposeUiFlags.isSemanticAutofillEnabled && isSemanticsInvalidated) {
-            val prev = _semanticsConfiguration
-            _semanticsConfiguration = calculateSemanticsConfiguration()
-            isSemanticsInvalidated = false
-            requireOwner().semanticsOwner.notifySemanticsChange(this, prev)
-        }
     }
 
     private fun resetModifierState() {
@@ -1303,7 +1270,7 @@
         }
     }
 
-    override val parentInfo: SemanticsInfo?
+    override val parentInfo: LayoutInfo?
         get() = parent
 
     override var isDeactivated = false
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 c08a929..ff19036 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
@@ -40,8 +40,8 @@
     internal var head: Modifier.Node = tail
         private set
 
-    internal val isUpdating: Boolean
-        get() = head.parent != null
+    private val isUpdating: Boolean
+        get() = head === SentinelHead
 
     private val aggregateChildKindSet: Int
         get() = head.aggregateChildKindSet
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
index f102b02..0ce80dd 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
@@ -1512,7 +1512,7 @@
                 override fun interceptOutOfBoundsChildEvents(node: Modifier.Node) = false
 
                 override fun shouldHitTestChildren(parentLayoutNode: LayoutNode) =
-                    parentLayoutNode.semanticsConfiguration?.isClearingSemantics != true
+                    parentLayoutNode.collapsedSemantics?.isClearingSemantics != true
 
                 override fun childHitTest(
                     layoutNode: LayoutNode,
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
index 655a320..ed5b7c2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
@@ -18,7 +18,6 @@
 package androidx.compose.ui.node
 
 import androidx.annotation.RestrictTo
-import androidx.collection.IntObjectMap
 import androidx.compose.runtime.Applier
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
@@ -48,7 +47,6 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.spatial.RectManager
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.font.FontFamily
@@ -70,9 +68,6 @@
     /** The root layout node in the component tree. */
     val root: LayoutNode
 
-    /** A mapping of semantic id to LayoutNode. */
-    val layoutNodes: IntObjectMap<LayoutNode>
-
     /** Draw scope reused for drawing speed up. */
     val sharedDrawScope: LayoutNodeDrawScope
 
@@ -134,8 +129,6 @@
 
     val pointerIconService: PointerIconService
 
-    val semanticsOwner: SemanticsOwner
-
     /** Provide a focus owner that controls focus within Compose. */
     val focusOwner: FocusOwner
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SemanticsModifierNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SemanticsModifierNode.kt
index 002be43..dd3e2f8 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SemanticsModifierNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SemanticsModifierNode.kt
@@ -87,14 +87,7 @@
     fun SemanticsPropertyReceiver.applySemantics()
 }
 
-/**
- * Invalidate semantics associated with this node. This will reset the [SemanticsConfiguration]
- * associated with the layout node backing this modifier node, and will re-calculate it the next
- * time the [SemanticsConfiguration] is read.
- */
-fun SemanticsModifierNode.invalidateSemantics() {
-    requireLayoutNode().invalidateSemantics()
-}
+fun SemanticsModifierNode.invalidateSemantics() = requireLayoutNode().invalidateSemantics()
 
 internal val SemanticsConfiguration.useMinimumTouchTarget: Boolean
     get() = getOrNull(SemanticsActions.OnClick) != null
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsInfo.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsInfo.kt
deleted file mode 100644
index 1f2cc5d..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsInfo.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2024 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.ui.semantics
-
-import androidx.compose.runtime.collection.MutableVector
-import androidx.compose.ui.layout.LayoutInfo
-import androidx.compose.ui.layout.Placeable
-import androidx.compose.ui.node.LayoutNode
-
-/**
- * This is an internal interface that can be used by [SemanticsListener]s to read semantic
- * information from layout nodes. The root [SemanticsInfo] can be accessed using
- * [SemanticsOwner.rootInfo], and particular [SemanticsInfo] can be looked up by their [semanticsId]
- * by using [SemanticsOwner.get].
- */
-internal interface SemanticsInfo : LayoutInfo {
-    /** The semantics configuration (Semantic properties and actions) associated with this node. */
-    val semanticsConfiguration: SemanticsConfiguration?
-
-    /**
-     * The [SemanticsInfo] of the parent.
-     *
-     * This includes parents that do not have any semantics modifiers.
-     */
-    override val parentInfo: SemanticsInfo?
-
-    /**
-     * Returns the children list sorted by their [LayoutNode.zIndex] first (smaller first) and the
-     * order they were placed via [Placeable.placeAt] by parent (smaller first). Please note that
-     * this list contains not placed items as well, so you have to manually filter them.
-     *
-     * Note that the object is reused so you shouldn't save it for later.
-     */
-    val childrenInfo: MutableVector<SemanticsInfo>
-}
-
-/** The semantics parent (nearest ancestor which has semantic properties). */
-internal fun SemanticsInfo.findSemanticsParent(): SemanticsInfo? {
-    var parent = parentInfo
-    while (parent != null) {
-        if (parent.semanticsConfiguration != null) return parent
-        parent = parent.parentInfo
-    }
-    return null
-}
-
-/** The nearest semantics ancestor that is merging descendants. */
-internal fun SemanticsInfo.findMergingSemanticsParent(): SemanticsInfo? {
-    var parent = parentInfo
-    while (parent != null) {
-        if (parent.semanticsConfiguration?.isMergingSemanticsOfDescendants == true) return parent
-        parent = parent.parentInfo
-    }
-    return null
-}
-
-internal inline fun SemanticsInfo.findSemanticsChildren(
-    includeDeactivated: Boolean = false,
-    block: (SemanticsInfo) -> Unit
-) {
-    val unvisitedStack = MutableVector<SemanticsInfo>(childrenInfo.size)
-    childrenInfo.forEachReversed { unvisitedStack += it }
-    while (unvisitedStack.isNotEmpty()) {
-        val child = unvisitedStack.removeAt(unvisitedStack.lastIndex)
-        when {
-            child.isDeactivated && !includeDeactivated -> continue
-            child.semanticsConfiguration != null -> block(child)
-            else -> child.childrenInfo.forEachReversed { unvisitedStack += it }
-        }
-    }
-}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsListener.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsListener.kt
deleted file mode 100644
index b51d7c8..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsListener.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2024 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.ui.semantics
-
-/** A listener that can be used to observe semantic changes. */
-internal interface SemanticsListener {
-
-    /**
-     * [onSemanticsChanged] is called when the [SemanticsConfiguration] of a LayoutNode changes, or
-     * when a node calls SemanticsModifierNode.invalidateSemantics.
-     *
-     * @param semanticsInfo the current [SemanticsInfo] of the layout node that has changed.
-     * @param previousSemanticsConfiguration the previous [SemanticsConfiguration] associated with
-     *   the layout node.
-     */
-    fun onSemanticsChanged(
-        semanticsInfo: SemanticsInfo,
-        previousSemanticsConfiguration: SemanticsConfiguration?
-    )
-}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
index 4bbacd0..35478d6 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
@@ -45,7 +45,7 @@
         layoutNode.nodes.head(Nodes.Semantics)!!.node,
         mergingEnabled,
         layoutNode,
-        layoutNode.semanticsConfiguration!!
+        layoutNode.collapsedSemantics!!
     )
 
 internal fun SemanticsNode(
@@ -70,7 +70,7 @@
         outerSemanticsNode.node,
         mergingEnabled,
         layoutNode,
-        layoutNode.semanticsConfiguration ?: SemanticsConfiguration()
+        layoutNode.collapsedSemantics ?: SemanticsConfiguration()
     )
 
 /**
@@ -99,7 +99,7 @@
             !isFake &&
                 replacedChildren.isEmpty() &&
                 layoutNode.findClosestParentNode {
-                    it.semanticsConfiguration?.isMergingSemanticsOfDescendants == true
+                    it.collapsedSemantics?.isMergingSemanticsOfDescendants == true
                 } == null
 
     /** The [LayoutInfo] that this is associated with. */
@@ -345,7 +345,7 @@
             if (mergingEnabled) {
                 node =
                     this.layoutNode.findClosestParentNode {
-                        it.semanticsConfiguration?.isMergingSemanticsOfDescendants == true
+                        it.collapsedSemantics?.isMergingSemanticsOfDescendants == true
                     }
             }
 
@@ -474,9 +474,7 @@
  * Executes [selector] on every parent of this [LayoutNode] and returns the closest [LayoutNode] to
  * return `true` from [selector] or null if [selector] returns false for all ancestors.
  */
-internal inline fun LayoutNode.findClosestParentNode(
-    selector: (LayoutNode) -> Boolean
-): LayoutNode? {
+internal fun LayoutNode.findClosestParentNode(selector: (LayoutNode) -> Boolean): LayoutNode? {
     var currentParent = this.parent
     while (currentParent != null) {
         if (selector(currentParent)) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsOwner.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsOwner.kt
index b987155..dffed0f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsOwner.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsOwner.kt
@@ -16,8 +16,6 @@
 
 package androidx.compose.ui.semantics
 
-import androidx.collection.IntObjectMap
-import androidx.collection.MutableObjectList
 import androidx.compose.ui.node.LayoutNode
 import androidx.compose.ui.util.fastForEach
 
@@ -25,8 +23,7 @@
 class SemanticsOwner
 internal constructor(
     private val rootNode: LayoutNode,
-    private val outerSemanticsNode: EmptySemanticsModifier,
-    private val nodes: IntObjectMap<LayoutNode>
+    private val outerSemanticsNode: EmptySemanticsModifier
 ) {
     /**
      * The root node of the semantics tree. Does not contain any unmerged data. May contain merged
@@ -50,22 +47,6 @@
                 unmergedConfig = SemanticsConfiguration()
             )
         }
-
-    internal val listeners = MutableObjectList<SemanticsListener>(2)
-
-    internal val rootInfo: SemanticsInfo
-        get() = rootNode
-
-    internal operator fun get(semanticsId: Int): SemanticsInfo? {
-        return nodes[semanticsId]
-    }
-
-    internal fun notifySemanticsChange(
-        semanticsInfo: SemanticsInfo,
-        previousSemanticsConfiguration: SemanticsConfiguration?
-    ) {
-        listeners.forEach { it.onSemanticsChanged(semanticsInfo, previousSemanticsConfiguration) }
-    }
 }
 
 /**
@@ -89,7 +70,6 @@
         .toList()
 }
 
-@Suppress("unused")
 @Deprecated(message = "Use a new overload instead", level = DeprecationLevel.HIDDEN)
 fun SemanticsOwner.getAllSemanticsNodes(mergingEnabled: Boolean) =
     getAllSemanticsNodes(mergingEnabled, true)
diff --git a/datastore/datastore-preferences/build.gradle b/datastore/datastore-preferences/build.gradle
index 9fb7310..47d0108 100644
--- a/datastore/datastore-preferences/build.gradle
+++ b/datastore/datastore-preferences/build.gradle
@@ -28,12 +28,8 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
-android{
-    namespace "androidx.datastore.preferences"
-}
 androidXMultiplatform {
     jvm()
     mac()
@@ -41,7 +37,17 @@
     ios()
     watchos()
     tvos()
-    android()
+    androidLibrary {
+        namespace = "androidx.datastore.preferences"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -93,7 +99,6 @@
     }
 }
 
-
 androidx {
     name = "Preferences DataStore"
     type = LibraryType.PUBLISHED_LIBRARY
diff --git a/datastore/datastore/build.gradle b/datastore/datastore/build.gradle
index 0933373..80d4bbd6 100644
--- a/datastore/datastore/build.gradle
+++ b/datastore/datastore/build.gradle
@@ -27,12 +27,8 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
-android {
-    namespace "androidx.datastore.datastore"
-}
 
 androidXMultiplatform {
     jvm()
@@ -41,7 +37,17 @@
     watchos()
     tvos()
     linux()
-    android()
+    androidLibrary {
+        namespace = "androidx.datastore.datastore"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
diff --git a/development/project-creator/compose-template/groupId/artifactId/build.gradle b/development/project-creator/compose-template/groupId/artifactId/build.gradle
index 9cde1b1..83fd2fb 100644
--- a/development/project-creator/compose-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/compose-template/groupId/artifactId/build.gradle
@@ -28,11 +28,20 @@
 plugins {
     id("AndroidXPlugin")
     id("AndroidXComposePlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "<PACKAGE>"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -97,9 +106,6 @@
     }
 }
 
-android {
-    namespace "<PACKAGE>"
-}
 
 androidx {
     name = "<NAME>"
diff --git a/docs/api_guidelines/dependencies.md b/docs/api_guidelines/dependencies.md
index 74b88cd..c6f1576 100644
--- a/docs/api_guidelines/dependencies.md
+++ b/docs/api_guidelines/dependencies.md
@@ -236,15 +236,19 @@
 }
 ```
 
-### System health {#dependencies-health}
+### Dependency considerations {#dependencies-health}
 
 Generally, Jetpack libraries should avoid dependencies that negatively impact
 developers without providing substantial benefit. Libraries should consider the
-system health implications of their dependencies, including:
+implications of their dependencies, including:
 
 -   Large dependencies where only a small portion is needed (e.g. APK bloat)
 -   Dependencies that slow down build times through annotation processing or
     compiler overhead
+-   Dependencies which do not maintain binary compatibility and conflict with
+    semantic versioning guarantees
+-   Dependencies that are intended for server environments and don't interact
+    well with the Android build toolchain (e.g. R8) or runtime (e.g. ART)
 
 #### Kotlin {#dependencies-kotlin}
 
@@ -281,6 +285,12 @@
 }
 ```
 
+#### GSON {#dependencies-gson}
+
+GSON relies heavily on reflection and interacts poorly with app optimization
+tools like R8. Instead, consider using `org.json` which is included in the
+Android platform SDK.
+
 #### Guava {#dependencies-guava}
 
 The full Guava library is very large and should only be used in cases where
diff --git a/graphics/graphics-shapes/build.gradle b/graphics/graphics-shapes/build.gradle
index 7212f00..000cc74 100644
--- a/graphics/graphics-shapes/build.gradle
+++ b/graphics/graphics-shapes/build.gradle
@@ -26,12 +26,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
-
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.graphics.shapes"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     desktop()
     linux()
     ios()
@@ -99,9 +107,6 @@
     }
 }
 
-android {
-    namespace "androidx.graphics.shapes"
-}
 
 androidx {
     name = "Graphics Shapes"
diff --git a/libraryversions.toml b/libraryversions.toml
index 5bb21b8..6ee9fb1 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -69,7 +69,7 @@
 GRAPHICS_CORE = "1.0.0"
 GRAPHICS_FILTERS = "1.0.0-alpha01"
 GRAPHICS_PATH = "1.0.0-rc01"
-GRAPHICS_SHAPES = "1.0.0-rc01"
+GRAPHICS_SHAPES = "1.1.0-alpha01"
 GRIDLAYOUT = "1.1.0-beta02"
 HEALTH_CONNECT = "1.1.0-alpha10"
 HEALTH_CONNECT_TESTING_QUARANTINE = "1.0.0-alpha01"
diff --git a/lifecycle/lifecycle-runtime-compose/build.gradle b/lifecycle/lifecycle-runtime-compose/build.gradle
index a802e2f..7a93d89 100644
--- a/lifecycle/lifecycle-runtime-compose/build.gradle
+++ b/lifecycle/lifecycle-runtime-compose/build.gradle
@@ -27,12 +27,31 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.lifecycle.runtime.compose"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+
+        compileSdk = 35
+        aarMetadata.minCompileSdk = 35
+
+        optimization {
+            it.consumerKeepRules.publish = true
+            it.consumerKeepRules.files.add(
+                new File(project.projectDir, "proguard-rules.pro")
+            )
+        }
+    }
     jvmStubs()
     linuxX64Stubs()
 
@@ -94,12 +113,3 @@
     samples(project(":lifecycle:lifecycle-runtime-compose:lifecycle-runtime-compose-samples"))
 }
 
-android {
-    compileSdk 35
-    
-    buildTypes.configureEach {
-        consumerProguardFiles "proguard-rules.pro"
-    }
-
-    namespace "androidx.lifecycle.runtime.compose"
-}
diff --git a/lifecycle/lifecycle-runtime-ktx/build.gradle b/lifecycle/lifecycle-runtime-ktx/build.gradle
index e660299..049067d 100644
--- a/lifecycle/lifecycle-runtime-ktx/build.gradle
+++ b/lifecycle/lifecycle-runtime-ktx/build.gradle
@@ -27,11 +27,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.lifecycle.ktx"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -60,6 +69,3 @@
     description = "Kotlin extensions for 'lifecycle' artifact"
 }
 
-android {
-    namespace "androidx.lifecycle.ktx"
-}
diff --git a/lifecycle/lifecycle-runtime-testing/build.gradle b/lifecycle/lifecycle-runtime-testing/build.gradle
index 430b902..89a61a8 100644
--- a/lifecycle/lifecycle-runtime-testing/build.gradle
+++ b/lifecycle/lifecycle-runtime-testing/build.gradle
@@ -27,11 +27,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.lifecycle.testing"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     desktop()
     mac()
     linux()
@@ -73,13 +82,10 @@
 
 androidx {
     name = "Lifecycle Runtime Testing"
-    type = LibraryType.PUBLISHED_LIBRARY
+    type = LibraryType.PUBLISHED_TEST_LIBRARY
     inceptionYear = "2019"
     description = "Testing utilities for 'lifecycle' artifact"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = false
 }
 
-android {
-    namespace "androidx.lifecycle.testing"
-}
diff --git a/lifecycle/lifecycle-viewmodel-testing/build.gradle b/lifecycle/lifecycle-viewmodel-testing/build.gradle
index bd1b11a..919a73e 100644
--- a/lifecycle/lifecycle-viewmodel-testing/build.gradle
+++ b/lifecycle/lifecycle-viewmodel-testing/build.gradle
@@ -29,11 +29,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.lifecycle.viewmodel.testing"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     desktop()
     mac()
     linux()
@@ -108,6 +117,3 @@
     metalavaK2UastEnabled = false
 }
 
-android {
-    namespace "androidx.lifecycle.viewmodel.testing"
-}
diff --git a/navigation/navigation-runtime/api/current.txt b/navigation/navigation-runtime/api/current.txt
index b801964..a4cc6458 100644
--- a/navigation/navigation-runtime/api/current.txt
+++ b/navigation/navigation-runtime/api/current.txt
@@ -113,6 +113,7 @@
     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 final boolean handleDeepLink(androidx.navigation.NavDeepLinkRequest request);
     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);
diff --git a/navigation/navigation-runtime/api/restricted_current.txt b/navigation/navigation-runtime/api/restricted_current.txt
index b801964..a4cc6458 100644
--- a/navigation/navigation-runtime/api/restricted_current.txt
+++ b/navigation/navigation-runtime/api/restricted_current.txt
@@ -113,6 +113,7 @@
     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 final boolean handleDeepLink(androidx.navigation.NavDeepLinkRequest request);
     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);
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
index 1fbe388d..95a9f20 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
@@ -3331,6 +3331,66 @@
 
     @UiThreadTest
     @Test
+    fun testHandleDeepLinkAsUri() {
+        val navController = createNavController()
+        val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
+        navController.setGraph(R.navigation.nav_simple)
+
+        val deepLink = Uri.parse("test-app://test/333")
+        val request = NavDeepLinkRequest.Builder.fromUri(deepLink).build()
+        assertWithMessage("NavController should handle deep links to its own graph")
+            .that(navController.handleDeepLink(request))
+            .isTrue()
+        // Verify that we navigated down to the deep link
+        assertThat(navigator.backStack.map { it.destination.id })
+            .containsExactly(R.id.start_test, R.id.nonNullableArg_test)
+            .inOrder()
+
+        val destination = navController.currentDestination
+        assertThat(destination?.id ?: 0).isEqualTo(R.id.nonNullableArg_test)
+    }
+
+    @UiThreadTest
+    @Test
+    fun testHandleDeepLink_InvalidUri() {
+        val navController = createNavController()
+        navController.setGraph(R.navigation.nav_simple)
+
+        val deepLink = Uri.parse("test-app://invalid/uri")
+        val request = NavDeepLinkRequest.Builder.fromUri(deepLink).build()
+        assertWithMessage("NavController should not match with any deeplink due to invalid uri")
+            .that(navController.handleDeepLink(request))
+            .isFalse()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testHandleDeepLink_MimeType() {
+        val navController = createNavController()
+        navController.setGraph(R.navigation.nav_simple)
+        val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
+        val deepLink = NavDeepLinkRequest(Uri.parse("invalidDeepLink.com"), null, "type/test")
+
+        navController.handleDeepLink(deepLink)
+        assertThat(navController.currentDestination?.id ?: 0).isEqualTo(R.id.second_test)
+        assertThat(navigator.backStack.size).isEqualTo(2)
+    }
+
+    @UiThreadTest
+    @Test
+    fun testHandleDeepLink_Action() {
+        val navController = createNavController()
+        navController.setGraph(R.navigation.nav_simple)
+        val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
+        val deepLink = NavDeepLinkRequest(null, "test.action", null)
+
+        navController.handleDeepLink(deepLink)
+        assertThat(navController.currentDestination?.id ?: 0).isEqualTo(R.id.second_test)
+        assertThat(navigator.backStack.size).isEqualTo(2)
+    }
+
+    @UiThreadTest
+    @Test
     fun testHandleDeepLinkActionMissingURI_nonNullableArg() {
         val navController = createNavController()
         navController.setGraph(R.navigation.nav_simple)
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
index ab95516..8efc3e2 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
@@ -1539,7 +1539,55 @@
             }
             return true
         }
-        if (flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0) {
+        return handleDeepLink(deepLink, args, flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0)
+    }
+
+    /**
+     * Checks the given NavDeepLinkRequest for a Navigation deep link and navigates to the
+     * destination if present.
+     *
+     * The [navigation graph][graph] should be set before calling this method.
+     *
+     * @param request The request that contains a valid deep link, an action or a mimeType.
+     * @return True if the navigation controller found a valid deep link and navigated to it.
+     * @throws IllegalStateException if deep link cannot be accessed from the current destination
+     * @see NavDestination.addDeepLink
+     */
+    @MainThread
+    public fun handleDeepLink(request: NavDeepLinkRequest): Boolean {
+        val currGraph = backQueue.getTopGraph()
+        val matchingDeepLink =
+            currGraph.matchDeepLinkComprehensive(
+                navDeepLinkRequest = request,
+                searchChildren = true,
+                searchParent = true,
+                lastVisited = currGraph
+            )
+        if (matchingDeepLink != null) {
+            val destination = matchingDeepLink.destination
+            val deepLink = destination.buildDeepLinkIds()
+            val globalArgs = Bundle()
+            val destinationArgs = destination.addInDefaultArgs(matchingDeepLink.matchingArgs)
+            if (destinationArgs != null) {
+                globalArgs.putAll(destinationArgs)
+            }
+            val args = arrayOfNulls<Bundle>(deepLink.size)
+            for (index in args.indices) {
+                val arguments = Bundle()
+                arguments.putAll(globalArgs)
+                args[index] = arguments
+            }
+            return handleDeepLink(deepLink, args, true)
+        }
+        return false
+    }
+
+    private fun handleDeepLink(
+        deepLink: IntArray,
+        args: Array<Bundle?>,
+        newTask: Boolean
+    ): Boolean {
+        if (newTask) {
             // Start with a cleared task starting at our root when we're on our own task
             if (!backQueue.isEmpty()) {
                 popBackStackInternal(_graph!!.id, true)
diff --git a/pdf/pdf-viewer/src/main/res/values-af/strings.xml b/pdf/pdf-viewer/src/main/res/values-af/strings.xml
index f62de4d..344991a 100644
--- a/pdf/pdf-viewer/src/main/res/values-af/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-af/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Volgende"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Maak toe"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Geen passende resultate nie"</string>
     <string name="action_edit" msgid="5882082700509010966">"Wysig lêer"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Voer wagwoord in om te ontsluit"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-am/strings.xml b/pdf/pdf-viewer/src/main/res/values-am/strings.xml
index 9251d8b..7db9b5a 100644
--- a/pdf/pdf-viewer/src/main/res/values-am/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-am/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"ቀጣይ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ዝጋ"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"ምንም የሚመሳሰሉ ውጤቶች የሉም"</string>
     <string name="action_edit" msgid="5882082700509010966">"ፋይል አርትዕ"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ለመክፈት የይለፍ ቃል ያስገቡ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ar/strings.xml b/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
index 7477408..f88ddb3 100644
--- a/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"التالي"</string>
     <string name="close_button_description" msgid="7379823906921067675">"إغلاق"</string>
     <string name="message_match_status" msgid="6288242289981639727">"‫<xliff:g id="POSITION">%1$d</xliff:g> من أصل <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"‫<xliff:g id="POSITION">%1$d</xliff:g> من إجمالي <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"ما مِن نتائج مطابقة"</string>
     <string name="action_edit" msgid="5882082700509010966">"تعديل الملف"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"يجب إدخال كلمة المرور لفتح القفل"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-as/strings.xml b/pdf/pdf-viewer/src/main/res/values-as/strings.xml
index 575762e..c5fbb0d 100644
--- a/pdf/pdf-viewer/src/main/res/values-as/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-as/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"পৰৱৰ্তী"</string>
     <string name="close_button_description" msgid="7379823906921067675">"বন্ধ কৰক"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"কোনো মিল থকা ফলাফল নাই"</string>
     <string name="action_edit" msgid="5882082700509010966">"ফাইল সম্পাদনা কৰক"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"আনলক কৰিবলৈ পাছৱৰ্ড দিয়ক"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-az/strings.xml b/pdf/pdf-viewer/src/main/res/values-az/strings.xml
index 56f789c..f058531 100644
--- a/pdf/pdf-viewer/src/main/res/values-az/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-az/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Növbəti"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Bağlayın"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Uyğun gələn nəticə yoxdur"</string>
     <string name="action_edit" msgid="5882082700509010966">"Faylı redaktə edin"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Kiliddən çıxarmaq üçün parol daxil edin"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-b+sr+Latn/strings.xml b/pdf/pdf-viewer/src/main/res/values-b+sr+Latn/strings.xml
index 98c7f5b..e43a0da 100644
--- a/pdf/pdf-viewer/src/main/res/values-b+sr+Latn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-b+sr+Latn/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Dalje"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zatvori"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Nema podudarnih rezultata"</string>
     <string name="action_edit" msgid="5882082700509010966">"Izmeni fajl"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Unesite lozinku za otključavanje"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-be/strings.xml b/pdf/pdf-viewer/src/main/res/values-be/strings.xml
index e5246b7..0d565d7 100644
--- a/pdf/pdf-viewer/src/main/res/values-be/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-be/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Далей"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Закрыць"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> з <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> з <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Супадзенняў няма"</string>
     <string name="action_edit" msgid="5882082700509010966">"Рэдагаваць файл"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Увядзіце пароль для разблакіроўкі"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-bg/strings.xml b/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
index 1963288..3af4c32 100644
--- a/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Напред"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Затваряне"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> от <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Няма съответстващи резултати"</string>
     <string name="action_edit" msgid="5882082700509010966">"Редактиране на файла"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Въведете паролата, за да отключите"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-bn/strings.xml b/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
index 7e9b6a8..523615d 100644
--- a/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"পরবর্তী"</string>
     <string name="close_button_description" msgid="7379823906921067675">"বন্ধ করুন"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"কোনও ফলাফল মিলছে না"</string>
     <string name="action_edit" msgid="5882082700509010966">"ফাইল এডিট করুন"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"আনলক করতে পাসওয়ার্ড লিখুন"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-bs/strings.xml b/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
index 6e2be84..58cb55b 100644
--- a/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Naprijed"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zatvaranje"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Nema podudarnih rezultata"</string>
     <string name="action_edit" msgid="5882082700509010966">"Uredite fajl"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Unesite lozinku da otključate fajl"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ca/strings.xml b/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
index e5237f2..e006cd2 100644
--- a/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Següent"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Tanca"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"No hi ha cap resultat coincident"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edita el fitxer"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Introdueix la contrasenya per desbloquejar-lo"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-cs/strings.xml b/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
index bb042a7..93a108c 100644
--- a/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Další"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zavřít"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> z <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Žádné výsledky neodpovídají"</string>
     <string name="action_edit" msgid="5882082700509010966">"Upravit soubor"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"K odemknutí zadejte heslo"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-da/strings.xml b/pdf/pdf-viewer/src/main/res/values-da/strings.xml
index 120231b..5a5ac17 100644
--- a/pdf/pdf-viewer/src/main/res/values-da/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-da/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Næste"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Luk"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ingen matchende resultater"</string>
     <string name="action_edit" msgid="5882082700509010966">"Rediger fil"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Angiv adgangskode for at låse op"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-de/strings.xml b/pdf/pdf-viewer/src/main/res/values-de/strings.xml
index 8af7f80..15c0a75 100644
--- a/pdf/pdf-viewer/src/main/res/values-de/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-de/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Weiter"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Schließen"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Keine passenden Ergebnisse"</string>
     <string name="action_edit" msgid="5882082700509010966">"Datei bearbeiten"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Gib zum Entsperren ein Passwort ein"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-el/strings.xml b/pdf/pdf-viewer/src/main/res/values-el/strings.xml
index 7f833eb..83efcf5 100644
--- a/pdf/pdf-viewer/src/main/res/values-el/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-el/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Επόμενο"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Κλείσιμο"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> από <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Δεν υπάρχουν αντίστοιχα αποτελέσματα"</string>
     <string name="action_edit" msgid="5882082700509010966">"Επεξεργασία αρχείου"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Εισαγάγετε τον κωδικό πρόσβασης για ξεκλείδωμα"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rAU/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rAU/strings.xml
index b4f73b8..e3344f7 100644
--- a/pdf/pdf-viewer/src/main/res/values-en-rAU/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-en-rAU/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Next"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Close"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"No matching results"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edit file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Enter password to unlock"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rCA/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rCA/strings.xml
index 74126a3..f9bb660 100644
--- a/pdf/pdf-viewer/src/main/res/values-en-rCA/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-en-rCA/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Next"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Close"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> of <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"No matching results"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edit file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Enter password to unlock"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rGB/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rGB/strings.xml
index b4f73b8..e3344f7 100644
--- a/pdf/pdf-viewer/src/main/res/values-en-rGB/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-en-rGB/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Next"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Close"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"No matching results"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edit file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Enter password to unlock"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rIN/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rIN/strings.xml
index b4f73b8..e3344f7 100644
--- a/pdf/pdf-viewer/src/main/res/values-en-rIN/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-en-rIN/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Next"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Close"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"No matching results"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edit file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Enter password to unlock"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-es-rUS/strings.xml b/pdf/pdf-viewer/src/main/res/values-es-rUS/strings.xml
index ecf2f42..ac55757a 100644
--- a/pdf/pdf-viewer/src/main/res/values-es-rUS/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-es-rUS/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Siguiente"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Cerrar"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"No hay resultados que coincidan"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editar el archivo"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Ingresa la contraseña para desbloquear"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-es/strings.xml b/pdf/pdf-viewer/src/main/res/values-es/strings.xml
index 48a146f..a8395fb 100644
--- a/pdf/pdf-viewer/src/main/res/values-es/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-es/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Siguiente"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Cerrar"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"No hay coincidencias"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editar archivo"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Introduce la contraseña para desbloquear"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-et/strings.xml b/pdf/pdf-viewer/src/main/res/values-et/strings.xml
index e23221de..a57f96c 100644
--- a/pdf/pdf-viewer/src/main/res/values-et/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-et/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Järgmine"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Sule"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Päringule vastavaid tulemusi pole"</string>
     <string name="action_edit" msgid="5882082700509010966">"Faili muutmine"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Avamiseks sisestage parool"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-eu/strings.xml b/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
index c408c2b..e46c3a2 100644
--- a/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Hurrengoa"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Itxi"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ez dago bat datorren emaitzarik"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editatu fitxategia"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Idatzi pasahitza desblokeatzeko"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
index e017f32..9fe5557 100644
--- a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"بعدی"</string>
     <string name="close_button_description" msgid="7379823906921067675">"بستن"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"نتیجه منطبقی پیدا نشد"</string>
     <string name="action_edit" msgid="5882082700509010966">"ویرایش فایل"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"گذرواژه را برای بازگشایی قفل وارد کنید"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fi/strings.xml b/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
index 9b9eb0a..e9e243ac 100644
--- a/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Seuraava"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Sulje"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ei tuloksia"</string>
     <string name="action_edit" msgid="5882082700509010966">"Muokkaa tiedostoa"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Poista lukitus lisäämällä salasana"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fr-rCA/strings.xml b/pdf/pdf-viewer/src/main/res/values-fr-rCA/strings.xml
index 564ac9f..462595c 100644
--- a/pdf/pdf-viewer/src/main/res/values-fr-rCA/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fr-rCA/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Suivant"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Fermer"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Aucun résultat correspondant"</string>
     <string name="action_edit" msgid="5882082700509010966">"Modifier le fichier"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Entrez le mot de passe pour déverrouiller le fichier"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fr/strings.xml b/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
index f8067f1..7b5333c 100644
--- a/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Suivant"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Fermer"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> sur <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Aucun résultat"</string>
     <string name="action_edit" msgid="5882082700509010966">"Modifier le fichier"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Saisissez le mot de passe pour procéder au déverrouillage"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-gl/strings.xml b/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
index e9996c3..f44eedd 100644
--- a/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Seguinte"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Pechar"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Non hai ningún resultado que coincida"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editar o ficheiro"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Introduce o contrasinal para desbloquear o ficheiro"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-gu/strings.xml b/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
index a976158..3a6a1fe 100644
--- a/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"આગળ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"બંધ કરો"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"કોઈ મેળ ખાતું પરિણામ નથી"</string>
     <string name="action_edit" msgid="5882082700509010966">"ફાઇલમાં ફેરફાર કરો"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"અનલૉક કરવા માટે પાસવર્ડ દાખલ કરો"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hi/strings.xml b/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
index 1904222..d7febf7 100644
--- a/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"आगे बढ़ें"</string>
     <string name="close_button_description" msgid="7379823906921067675">"बंद करें"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g> में से <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"कोई मिलता-जुलता नतीजा नहीं मिला"</string>
     <string name="action_edit" msgid="5882082700509010966">"फ़ाइल में बदलाव करें"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"अनलॉक करने के लिए पासवर्ड डालें"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hr/strings.xml b/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
index d2be613..69663f2 100644
--- a/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Sljedeće"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zatvori"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Nema podudarnih rezultata"</string>
     <string name="action_edit" msgid="5882082700509010966">"Uređivanje datoteke"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Unesite zaporku za otključavanje"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hu/strings.xml b/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
index 13cefe9..746c393 100644
--- a/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Következő"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Bezárás"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="TOTAL">%2$d</xliff:g>/<xliff:g id="POSITION">%1$d</xliff:g>."</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g>/<xliff:g id="POSITION">%1$d</xliff:g>."</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Nincs találat"</string>
     <string name="action_edit" msgid="5882082700509010966">"Fájl szerkesztése"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"A feloldáshoz írja be a jelszót"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hy/strings.xml b/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
index 53b5c63..0930a77 100644
--- a/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Հաջորդը"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Փակել"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g>՝ <xliff:g id="TOTAL">%2$d</xliff:g>-ից"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Համապատասխանող արդյունքներ չկան"</string>
     <string name="action_edit" msgid="5882082700509010966">"Փոփոխել ֆայլը"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Մուտքագրեք գաղտնաբառը՝ ապակողպելու համար"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-in/strings.xml b/pdf/pdf-viewer/src/main/res/values-in/strings.xml
index d1c6170b..3b84829 100644
--- a/pdf/pdf-viewer/src/main/res/values-in/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-in/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Berikutnya"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Tutup"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Tidak ada hasil yang cocok"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edit file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Masukkan sandi untuk membuka kunci"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-is/strings.xml b/pdf/pdf-viewer/src/main/res/values-is/strings.xml
index 845c448..84ae8bb 100644
--- a/pdf/pdf-viewer/src/main/res/values-is/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-is/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Næsta"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Loka"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Engar samsvarandi niðurstöður fundust"</string>
     <string name="action_edit" msgid="5882082700509010966">"Breyta skrá"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Sláðu inn aðgangsorð til að opna"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-it/strings.xml b/pdf/pdf-viewer/src/main/res/values-it/strings.xml
index bea8957..b566885 100644
--- a/pdf/pdf-viewer/src/main/res/values-it/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-it/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Avanti"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Chiudi"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Nessun risultato corrispondente"</string>
     <string name="action_edit" msgid="5882082700509010966">"Modifica file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Inserisci la password per sbloccare il file"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-iw/strings.xml b/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
index e7adcaa..08eb4b5 100644
--- a/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"הבא"</string>
     <string name="close_button_description" msgid="7379823906921067675">"סגירה"</string>
     <string name="message_match_status" msgid="6288242289981639727">"‫<xliff:g id="POSITION">%1$d</xliff:g> מתוך <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"לא נמצאו תוצאות תואמות"</string>
     <string name="action_edit" msgid="5882082700509010966">"עריכת הקובץ"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"צריך להזין סיסמה לביטול הנעילה"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ja/strings.xml b/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
index e2161ea..09692f7 100644
--- a/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"次へ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"閉じる"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"一致する結果がありません"</string>
     <string name="action_edit" msgid="5882082700509010966">"ファイルを編集"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ロックを解除するには、パスワードを入力してください"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ka/strings.xml b/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
index 1d76eda..e131512 100644
--- a/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"შემდეგი"</string>
     <string name="close_button_description" msgid="7379823906921067675">"დახურვა"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g>-დან <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"შედეგებში არ არის დამთხვევა"</string>
     <string name="action_edit" msgid="5882082700509010966">"ფაილის რედაქტირება"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"პაროლის შეყვანა განბლოკვისთვის"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-kk/strings.xml b/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
index 6640153..31e081d 100644
--- a/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Келесі"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Жабу"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Сәйкес нәтижелер табылмады."</string>
     <string name="action_edit" msgid="5882082700509010966">"Файлды өңдеу"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Құлыпты ашу үшін құпия сөзді енгізіңіз."</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-km/strings.xml b/pdf/pdf-viewer/src/main/res/values-km/strings.xml
index 11cd884..5ce58c9 100644
--- a/pdf/pdf-viewer/src/main/res/values-km/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-km/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"បន្ទាប់"</string>
     <string name="close_button_description" msgid="7379823906921067675">"បិទ"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> នៃ <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"គ្មានលទ្ធផល​ត្រូវគ្នាទេ"</string>
     <string name="action_edit" msgid="5882082700509010966">"កែ​ឯកសារ"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"បញ្ចូល​ពាក្យ​សម្ងាត់ ដើម្បី​ដោះ​សោ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-kn/strings.xml b/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
index 65e39a0..a94de26 100644
--- a/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"ಮುಂದಿನದು"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ಮುಚ್ಚಿರಿ"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"ಯಾವುದೇ ಹೊಂದಾಣಿಕೆಯ ಫಲಿತಾಂಶಗಳಿಲ್ಲ"</string>
     <string name="action_edit" msgid="5882082700509010966">"ಫೈಲ್ ಎಡಿಟ್‌ ಮಾಡಿ"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ಪಾಸವರ್ಡ್‌ ಅನ್ನು ನಮೂದಿಸಿ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ko/strings.xml b/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
index 0726b77..2dc42f3 100644
--- a/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"다음"</string>
     <string name="close_button_description" msgid="7379823906921067675">"닫기"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"일치하는 결과 없음"</string>
     <string name="action_edit" msgid="5882082700509010966">"파일 수정"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"잠금 해제하려면 비밀번호 입력"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ky/strings.xml b/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
index 1a2783b..d88a930 100644
--- a/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Кийинки"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Жабуу"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Эч нерсе табылган жок"</string>
     <string name="action_edit" msgid="5882082700509010966">"Файлды түзөтүү"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Кулпусун ачуу үчүн сырсөздү териңиз"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-lo/strings.xml b/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
index 6eee324..4f4a7379 100644
--- a/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"ຕໍ່ໄປ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ປິດ"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"ບໍ່ມີຜົນໄດ້ຮັບທີ່ກົງກັນ"</string>
     <string name="action_edit" msgid="5882082700509010966">"ແກ້ໄຂໄຟລ໌"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ໃສ່ລະຫັດເພື່ອປົດລັອກ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-lt/strings.xml b/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
index 44ef381..aea04bf 100644
--- a/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Kitas"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Uždaryti"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> iš <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Atitikusių rezultatų nerasta"</string>
     <string name="action_edit" msgid="5882082700509010966">"Redaguoti failą"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Įveskite slaptažodį, kad atrakintumėte"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-lv/strings.xml b/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
index 62b43d2..8e489b8 100644
--- a/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Tālāk"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Aizvērt"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"numur <xliff:g id="POSITION">%1$d</xliff:g>, kopējais skaits ir <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Nav atbilstošu rezultātu."</string>
     <string name="action_edit" msgid="5882082700509010966">"Rediģēt failu"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Lai atbloķētu, ievadiet paroli."</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-mk/strings.xml b/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
index 86424ba..f7b0a43 100644
--- a/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Следно"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Затвори"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Нема резултати што се совпаѓаат"</string>
     <string name="action_edit" msgid="5882082700509010966">"Изменете ја датотеката"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Внесете лозинка за да отклучите"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ml/strings.xml b/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
index e1c7e40..18dda28 100644
--- a/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"അടുത്തത്"</string>
     <string name="close_button_description" msgid="7379823906921067675">"അടയ്ക്കുക"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g>-ൽ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"പൊരുത്തപ്പെടുന്ന ഫലങ്ങളൊന്നുമില്ല"</string>
     <string name="action_edit" msgid="5882082700509010966">"ഫയൽ എഡിറ്റ് ചെയ്യുക"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"അൺലോക്ക് ചെയ്യാൻ പാസ്‌വേഡ് നൽകുക"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-mn/strings.xml b/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
index eee4b83..5a406cd 100644
--- a/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Дараах"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Хаах"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ямар ч тохирох илэрц байхгүй"</string>
     <string name="action_edit" msgid="5882082700509010966">"Файлыг засах"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Түгжээг тайлахын тулд нууц үг оруулна уу"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-mr/strings.xml b/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
index 73892fc..663888f 100644
--- a/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"पुढील"</string>
     <string name="close_button_description" msgid="7379823906921067675">"बंद करा"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g> पैकी <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"कोणतेही जुळणारे परिणाम नाहीत"</string>
     <string name="action_edit" msgid="5882082700509010966">"फाइल संपादित करा"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"अनलॉक करण्यासाठी पासवर्ड एंटर करा"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ms/strings.xml b/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
index 7d642d7..c4565f0 100644
--- a/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Seterusnya"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Tutup"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> daripada <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Tiada hasil carian yang sepadan"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edit fail"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Masukkan kata laluan untuk membuka kunci"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-my/strings.xml b/pdf/pdf-viewer/src/main/res/values-my/strings.xml
index e642765..09ff37e 100644
--- a/pdf/pdf-viewer/src/main/res/values-my/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-my/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"ရှေ့သို့"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ပိတ်ရန်"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"ကိုက်ညီသောရလဒ် မရှိပါ"</string>
     <string name="action_edit" msgid="5882082700509010966">"ဖိုင် တည်းဖြတ်ရန်"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ဖွင့်ရန် စကားဝှက်ထည့်ပါ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-nb/strings.xml b/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
index 163e356..cb39104 100644
--- a/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Neste"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Lukk"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ingen treff"</string>
     <string name="action_edit" msgid="5882082700509010966">"Endre filen"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Skriv inn passordet for å låse opp"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ne/strings.xml b/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
index 4530550..5ef47e9 100644
--- a/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"अर्को"</string>
     <string name="close_button_description" msgid="7379823906921067675">"बन्द गर्नुहोस्"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"कुनै पनि मिल्दोजुल्दो परिणाम भेटिएन"</string>
     <string name="action_edit" msgid="5882082700509010966">"फाइल सम्पादन गर्नुहोस्"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"अनलक गर्न पासवर्ड हाल्नुहोस्"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-nl/strings.xml b/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
index 1ddbf68..25fe496 100644
--- a/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Volgende"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Sluiten"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> van <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Geen overeenkomende resultaten"</string>
     <string name="action_edit" msgid="5882082700509010966">"Bestand bewerken"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Voer het wachtwoord in om te ontgrendelen"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-or/strings.xml b/pdf/pdf-viewer/src/main/res/values-or/strings.xml
index 4b08b7b..e67a2f5 100644
--- a/pdf/pdf-viewer/src/main/res/values-or/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-or/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"ପରବର୍ତ୍ତୀ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g>ର <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"ମେଳ ହେଉଥିବା କୌଣସି ଫଳାଫଳ ନାହିଁ"</string>
     <string name="action_edit" msgid="5882082700509010966">"ଫାଇଲକୁ ଏଡିଟ କରନ୍ତୁ"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ଅନଲକ କରିବା ପାଇଁ ପାସୱାର୍ଡ ଲେଖନ୍ତୁ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pa/strings.xml b/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
index e68fbfa..b4845ba 100644
--- a/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"ਅੱਗੇ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ਬੰਦ ਕਰੋ"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"ਕੋਈ ਮੇਲ ਖਾਂਦਾ ਨਤੀਜਾ ਨਹੀਂ"</string>
     <string name="action_edit" msgid="5882082700509010966">"ਫ਼ਾਈਲ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pl/strings.xml b/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
index 3d52bbc..848f550 100644
--- a/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Dalej"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zamknij"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> z <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Brak pasujących wyników"</string>
     <string name="action_edit" msgid="5882082700509010966">"Edytuj plik"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Podaj hasło, aby odblokować"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pt-rBR/strings.xml b/pdf/pdf-viewer/src/main/res/values-pt-rBR/strings.xml
index 57583b90..642730e 100644
--- a/pdf/pdf-viewer/src/main/res/values-pt-rBR/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pt-rBR/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Próxima"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Fechar"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Nenhum resultado encontrado"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editar arquivo"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Digite a senha para desbloquear"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pt-rPT/strings.xml b/pdf/pdf-viewer/src/main/res/values-pt-rPT/strings.xml
index 17901b0..667143f 100644
--- a/pdf/pdf-viewer/src/main/res/values-pt-rPT/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pt-rPT/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Seguinte"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Fechar"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Sem resultados correspondentes"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editar ficheiro"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Introduza a palavra-passe para desbloquear"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pt/strings.xml b/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
index 57583b90..642730e 100644
--- a/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Próxima"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Fechar"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Nenhum resultado encontrado"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editar arquivo"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Digite a senha para desbloquear"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ro/strings.xml b/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
index f33ce79..ea88bec 100644
--- a/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Înainte"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Închide"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Niciun rezultat"</string>
     <string name="action_edit" msgid="5882082700509010966">"Editează fișierul"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Introdu parola pentru a debloca"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ru/strings.xml b/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
index b3bed54..d062234 100644
--- a/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Далее"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Закрыть"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> из <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ничего не найдено."</string>
     <string name="action_edit" msgid="5882082700509010966">"Редактировать файл"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Введите пароль для разблокировки."</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-si/strings.xml b/pdf/pdf-viewer/src/main/res/values-si/strings.xml
index 7aeb8c8..3c22ba7 100644
--- a/pdf/pdf-viewer/src/main/res/values-si/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-si/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"මීළඟ"</string>
     <string name="close_button_description" msgid="7379823906921067675">"වසන්න"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"ගැළපෙන ප්‍රතිඵල නැත"</string>
     <string name="action_edit" msgid="5882082700509010966">"ගොනුව සංස්කරණ කරන්න"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"අගුලු හැරීමට මුරපදය ඇතුළත් කරන්න"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sk/strings.xml b/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
index 2c4e7b4..8fdcc4c 100644
--- a/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Ďalej"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zavrieť"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Žiadne zodpovedajúce výsledky"</string>
     <string name="action_edit" msgid="5882082700509010966">"Upraviť súbor"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Zadajte heslo na odomknutie"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sl/strings.xml b/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
index 5ff5caa..e43931d 100644
--- a/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Naprej"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Zapri"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Ni ustreznih rezultatov"</string>
     <string name="action_edit" msgid="5882082700509010966">"Urejanje datoteke"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Vnesite geslo za odklepanje"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sq/strings.xml b/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
index a78b08a..482261d 100644
--- a/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Para"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Mbyll"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Nuk përputhet asnjë rezultat"</string>
     <string name="action_edit" msgid="5882082700509010966">"Modifiko skedarin"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Fut fjalëkalimin për ta shkyçur"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sr/strings.xml b/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
index 61074fd..ccd521a 100644
--- a/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Даље"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Затвори"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> од <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Нема подударних резултата"</string>
     <string name="action_edit" msgid="5882082700509010966">"Измени фајл"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Унесите лозинку за откључавање"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sv/strings.xml b/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
index e756be8..edbbf58 100644
--- a/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Nästa"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Stäng"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Det finns inga matchande resultat"</string>
     <string name="action_edit" msgid="5882082700509010966">"Redigera fil"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Ange lösenord för att låsa upp"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sw/strings.xml b/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
index 9f50a92a..f26bdf5 100644
--- a/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Endelea"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Funga"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> kati ya <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Hakuna matokeo yanayolingana"</string>
     <string name="action_edit" msgid="5882082700509010966">"Badilisha faili"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Weka nenosiri ili ufungue"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ta/strings.xml b/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
index 3c329ca..56321e0 100644
--- a/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"அடுத்ததற்குச் செல்லும்"</string>
     <string name="close_button_description" msgid="7379823906921067675">"மூடும்"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"பொருந்தும் முடிவுகள் எதுவுமில்லை"</string>
     <string name="action_edit" msgid="5882082700509010966">"ஃபைலைத் திருத்து"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"அன்லாக் செய்ய கடவுச்சொல்லை டைப் செய்யவும்"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-te/strings.xml b/pdf/pdf-viewer/src/main/res/values-te/strings.xml
index 1b0c0d8..3cc15c5 100644
--- a/pdf/pdf-viewer/src/main/res/values-te/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-te/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"తర్వాత"</string>
     <string name="close_button_description" msgid="7379823906921067675">"మూసివేయండి"</string>
     <string name="message_match_status" msgid="6288242289981639727">"మొత్తం <xliff:g id="TOTAL">%2$d</xliff:g>లో <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="TOTAL">%2$d</xliff:g>లో <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"మ్యాచ్ అయ్యే ఫలితాలు ఏవీ లేవు"</string>
     <string name="action_edit" msgid="5882082700509010966">"ఫైల్‌ను ఎడిట్ చేయండి"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"అన్‌లాక్ చేయడానికి పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-th/strings.xml b/pdf/pdf-viewer/src/main/res/values-th/strings.xml
index 17236b8..3f4cacb 100644
--- a/pdf/pdf-viewer/src/main/res/values-th/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-th/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"ถัดไป"</string>
     <string name="close_button_description" msgid="7379823906921067675">"ปิด"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> จาก <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"ไม่มีผลลัพธ์ที่ตรงกัน"</string>
     <string name="action_edit" msgid="5882082700509010966">"แก้ไขไฟล์"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"ป้อนรหัสผ่านเพื่อปลดล็อก"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-tl/strings.xml b/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
index 1daaa55..8dded5f 100644
--- a/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"Susunod"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Isara"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> sa <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"Walang tumutugmang resulta"</string>
     <string name="action_edit" msgid="5882082700509010966">"I-edit ang file"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Ilagay ang password para i-unlock"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-tr/strings.xml b/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
index c378486..d247153 100644
--- a/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Sonraki"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Kapat"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Eşleşen sonuç yok"</string>
     <string name="action_edit" msgid="5882082700509010966">"Dosyayı düzenle"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Kilidi açmak için şifreyi girin"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-uk/strings.xml b/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
index 358244d..11c4ecf 100644
--- a/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Далі"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Закрити"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Немає результатів"</string>
     <string name="action_edit" msgid="5882082700509010966">"Редагувати файл"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Введіть пароль, щоб розблокувати"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ur/strings.xml b/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
index 97c7973..12ccee6 100644
--- a/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"اگلا"</string>
     <string name="close_button_description" msgid="7379823906921067675">"بند کریں"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="TOTAL">%2$d</xliff:g> / <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"<xliff:g id="POSITION">%1$d</xliff:g> از <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"کوئی مماثل نتائج نہیں ہیں"</string>
     <string name="action_edit" msgid="5882082700509010966">"فائل میں ترمیم کریں"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"غیر مقفل کرنے کیلئے پاس ورڈ درج کریں"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-uz/strings.xml b/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
index eaea88b..82dd413 100644
--- a/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Keyingisi"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Yopish"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Mos keladigani topilmadi"</string>
     <string name="action_edit" msgid="5882082700509010966">"Faylni tahrirlash"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Ochish uchun parolni kiriting"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-vi/strings.xml b/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
index 1960c80..42e04e9 100644
--- a/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Tiếp theo"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Đóng"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Không có kết quả phù hợp"</string>
     <string name="action_edit" msgid="5882082700509010966">"Chỉnh sửa tệp"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Nhập mật khẩu để mở khoá"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zh-rCN/strings.xml b/pdf/pdf-viewer/src/main/res/values-zh-rCN/strings.xml
index cf29a52..343768c 100644
--- a/pdf/pdf-viewer/src/main/res/values-zh-rCN/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-zh-rCN/strings.xml
@@ -47,6 +47,7 @@
     <string name="next_button_description" msgid="4702699322249103693">"下一页"</string>
     <string name="close_button_description" msgid="7379823906921067675">"关闭"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="match_status_description" msgid="4996847358326345288">"第 <xliff:g id="POSITION">%1$d</xliff:g> 个(共 <xliff:g id="TOTAL">%2$d</xliff:g> 个)"</string>
     <string name="message_no_match_status" msgid="5929387004361286433">"没有符合条件的结果"</string>
     <string name="action_edit" msgid="5882082700509010966">"编辑文件"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"请输入密码进行解锁"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zh-rHK/strings.xml b/pdf/pdf-viewer/src/main/res/values-zh-rHK/strings.xml
index 06c8e92..984fbe1 100644
--- a/pdf/pdf-viewer/src/main/res/values-zh-rHK/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-zh-rHK/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"下一個"</string>
     <string name="close_button_description" msgid="7379823906921067675">"閂"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"找不到相符的結果"</string>
     <string name="action_edit" msgid="5882082700509010966">"編輯檔案"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"輸入密碼即可解鎖"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zh-rTW/strings.xml b/pdf/pdf-viewer/src/main/res/values-zh-rTW/strings.xml
index 12b583f..915cd4a 100644
--- a/pdf/pdf-viewer/src/main/res/values-zh-rTW/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-zh-rTW/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"下一個"</string>
     <string name="close_button_description" msgid="7379823906921067675">"關閉"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"找不到相符的結果"</string>
     <string name="action_edit" msgid="5882082700509010966">"編輯檔案"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"輸入密碼即可解鎖"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zu/strings.xml b/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
index a3ad158..23f95f7 100644
--- a/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
@@ -47,6 +47,8 @@
     <string name="next_button_description" msgid="4702699322249103693">"Okulandelayo"</string>
     <string name="close_button_description" msgid="7379823906921067675">"Vala"</string>
     <string name="message_match_status" msgid="6288242289981639727">"<xliff:g id="POSITION">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <!-- no translation found for match_status_description (4996847358326345288) -->
+    <skip />
     <string name="message_no_match_status" msgid="5929387004361286433">"Ayikho imiphumela efanayo"</string>
     <string name="action_edit" msgid="5882082700509010966">"Hlela ifayela"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Faka iphasiwedi ukuvula"</string>
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
index bf4537a..28f9f0c 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
@@ -16,10 +16,8 @@
 
 package androidx.room.ext
 
-import androidx.room.compiler.processing.XConstructorElement
 import androidx.room.compiler.processing.XElement
 import androidx.room.compiler.processing.XExecutableParameterElement
-import androidx.room.compiler.processing.XFieldElement
 import androidx.room.compiler.processing.XTypeElement
 import kotlin.contracts.contract
 
@@ -28,7 +26,7 @@
     return this.hasAnnotation(androidx.room.Entity::class)
 }
 
-fun XTypeElement.getValueClassUnderlyingInfo(): ValueClassInfo {
+fun XTypeElement.getValueClassUnderlyingElement(): XExecutableParameterElement {
     check(this.isValueClass()) {
         "Can't get value class property, type element '$this' is not a value class"
     }
@@ -36,21 +34,12 @@
     // * Primary constructor is required for value class
     // * Value class must have exactly one primary constructor parameter
     // * Value class primary constructor must only have final read-only (val) property parameter
-    val constructor =
-        checkNotNull(this.findPrimaryConstructor()) {
+    return checkNotNull(this.findPrimaryConstructor()) {
             "Couldn't find primary constructor for value class."
         }
-    val param = constructor.parameters.first()
-    val field = getDeclaredFields().first { it.name == param.name }
-    return ValueClassInfo(constructor, param, field)
+        .parameters
+        .single()
 }
 
-/** Store information about the underlying value property of a Kotlin value class */
-class ValueClassInfo(
-    val constructor: XConstructorElement,
-    val parameter: XExecutableParameterElement,
-    val field: XFieldElement,
-)
-
 /** Suffix of the Kotlin synthetic class created interface method implementations. */
 const val DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 86c5e95..798bfeb 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -28,7 +28,7 @@
 import androidx.room.ext.CollectionTypeNames.LONG_SPARSE_ARRAY
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.GuavaTypeNames
-import androidx.room.ext.getValueClassUnderlyingInfo
+import androidx.room.ext.getValueClassUnderlyingElement
 import androidx.room.ext.isByteBuffer
 import androidx.room.ext.isEntityElement
 import androidx.room.ext.isNotByte
@@ -377,15 +377,12 @@
         val typeElement = type.typeElement
         if (typeElement?.isValueClass() == true) {
             // Extract the type value of the Value class element
-            val underlyingInfo = typeElement.getValueClassUnderlyingInfo()
-            if (underlyingInfo.constructor.isPrivate() || underlyingInfo.field.getter == null) {
-                return null
-            }
+            val underlyingProperty = typeElement.getValueClassUnderlyingElement()
             val underlyingTypeColumnAdapter =
                 findColumnTypeAdapter(
                     // Find an adapter for the non-null underlying type, nullability will be handled
                     // by the value class adapter.
-                    out = underlyingInfo.parameter.asMemberOf(type).makeNonNullable(),
+                    out = underlyingProperty.asMemberOf(type).makeNonNullable(),
                     affinity = affinity,
                     skipDefaultConverter = false
                 ) ?: return null
@@ -394,7 +391,7 @@
                 valueTypeColumnAdapter = underlyingTypeColumnAdapter,
                 affinity = underlyingTypeColumnAdapter.typeAffinity,
                 out = type,
-                valuePropertyName = underlyingInfo.parameter.name
+                valuePropertyName = underlyingProperty.name
             )
         }
         return when {
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
index db835d4..1e314bf 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
@@ -24,7 +24,7 @@
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
 import androidx.room.compiler.processing.util.compileFiles
-import androidx.room.compiler.processing.util.runKspTest
+import androidx.room.runKspTestWithK1
 import androidx.room.runProcessorTestWithK1
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -225,44 +225,25 @@
                 """
             package foo
             class Subject {
-              fun uLongFunction(): ULong = TODO()
-              fun durationFunction(): kotlin.time.Duration = TODO()
+              fun makeULong(): ULong {
+                TODO()
+              }
             }
             """
                     .trimIndent()
             )
-        runKspTest(
+        runKspTestWithK1(
             sources = listOf(src),
             config =
                 XProcessingEnvConfig.DEFAULT.copy(excludeMethodsWithInvalidJvmSourceNames = false)
         ) { invocation ->
             val subject = invocation.processingEnv.requireTypeElement("foo.Subject")
-            subject
-                .getDeclaredMethods()
-                .first { it.name == "uLongFunction" }
-                .let { uLongFunction ->
-                    val returnType = uLongFunction.returnType
-                    val info = checkNotNull(returnType.typeElement).getValueClassUnderlyingInfo()
-                    assertThat(info.parameter.name).isEqualTo("data")
-                    assertThat(info.field.name).isEqualTo("data")
-                    assertThat(info.parameter.type)
-                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
-                    assertThat(info.field.type)
-                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
-                }
-            subject
-                .getDeclaredMethods()
-                .first { it.name == "durationFunction" }
-                .let { durationFunction ->
-                    val returnType = durationFunction.returnType
-                    val info = checkNotNull(returnType.typeElement).getValueClassUnderlyingInfo()
-                    assertThat(info.parameter.name).isEqualTo("rawValue")
-                    assertThat(info.field.name).isEqualTo("rawValue")
-                    assertThat(info.parameter.type)
-                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
-                    assertThat(info.field.type)
-                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
-                }
+            val returnType =
+                subject.getDeclaredMethods().single { it.name == "makeULong" }.returnType
+            val prop = checkNotNull(returnType.typeElement).getValueClassUnderlyingElement()
+            assertThat(prop.name).isEqualTo("data")
+            assertThat(prop.type)
+                .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
         }
     }
 
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index d43a813..29cbd79 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -30,7 +30,6 @@
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
 import androidx.room.compiler.processing.util.compileFiles
-import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.GuavaUtilConcurrentTypeNames
@@ -196,6 +195,7 @@
             Source.java(
                 "foo.bar.Fruit",
                 """ package foo.bar;
+                import androidx.room.*;
                 enum Fruit {
                     APPLE,
                     BANANA,
@@ -222,6 +222,7 @@
             Source.kotlin(
                 "Foo.kt",
                 """
+            import androidx.room.*
             @JvmInline
             value class IntValueClass(val data: Int)
             @JvmInline
@@ -281,6 +282,7 @@
             Source.kotlin(
                 "Foo.kt",
                 """
+            import androidx.room.*
             @JvmInline
             value class Foo(val value : Int) {
                 val double
@@ -290,78 +292,15 @@
                     .trimIndent()
             )
 
-        runKspTest(sources = listOf(source)) { invocation ->
-            val store =
-                TypeAdapterStore.create(
-                    context = invocation.context,
-                    builtInConverterFlags = BuiltInConverterFlags.DEFAULT
-                )
-            val typeElement = invocation.processingEnv.requireTypeElement("Foo")
-            val result =
-                store.findColumnTypeAdapter(
-                    out = typeElement.type,
-                    affinity = null,
-                    skipDefaultConverter = false
-                )
-            assertThat(result).isInstanceOf<ValueClassConverterWrapper>()
-        }
-    }
-
-    @Test
-    fun testValueClassWithPrivateVal() {
-        val source =
-            Source.kotlin(
-                "Foo.kt",
-                """
-            @JvmInline
-            value class Foo(private val value : Int)
-            """
-                    .trimIndent()
+        runProcessorTestWithK1(sources = listOf(source)) { invocation ->
+            TypeAdapterStore.create(
+                context = invocation.context,
+                builtInConverterFlags = BuiltInConverterFlags.DEFAULT
             )
-
-        runKspTest(sources = listOf(source)) { invocation ->
-            val store =
-                TypeAdapterStore.create(
-                    context = invocation.context,
-                    builtInConverterFlags = BuiltInConverterFlags.DEFAULT
-                )
             val typeElement = invocation.processingEnv.requireTypeElement("Foo")
-            val result =
-                store.findColumnTypeAdapter(
-                    out = typeElement.type,
-                    affinity = null,
-                    skipDefaultConverter = false
-                )
-            assertThat(result).isNull()
-        }
-    }
-
-    @Test
-    fun testValueClassWithPrivateConstructor() {
-        val source =
-            Source.kotlin(
-                "Foo.kt",
-                """
-            @JvmInline
-            value class Foo private constructor(val value : Int)
-            """
-                    .trimIndent()
-            )
-
-        runKspTest(sources = listOf(source)) { invocation ->
-            val store =
-                TypeAdapterStore.create(
-                    context = invocation.context,
-                    builtInConverterFlags = BuiltInConverterFlags.DEFAULT
-                )
-            val typeElement = invocation.processingEnv.requireTypeElement("Foo")
-            val result =
-                store.findColumnTypeAdapter(
-                    out = typeElement.type,
-                    affinity = null,
-                    skipDefaultConverter = false
-                )
-            assertThat(result).isNull()
+            assertThat(typeElement.getDeclaredFields()).hasSize(1)
+            assertThat(typeElement.getDeclaredFields().single().type.asTypeName())
+                .isEqualTo(PRIMITIVE_INT)
         }
     }
 
diff --git a/room/room-testing/build.gradle b/room/room-testing/build.gradle
index 14a4823..4678633 100644
--- a/room/room-testing/build.gradle
+++ b/room/room-testing/build.gradle
@@ -22,7 +22,6 @@
  * modifying its settings.
  */
 
-
 import androidx.build.KotlinTarget
 import androidx.build.PlatformIdentifier
 import androidx.build.LibraryType
@@ -30,11 +29,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.room.testing"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     ios()
     jvm()
     linux()
@@ -88,9 +96,6 @@
     }
 }
 
-android {
-    namespace "androidx.room.testing"
-}
 
 androidx {
     name = "Room Testing"
diff --git a/savedstate/savedstate/api/current.txt b/savedstate/savedstate/api/current.txt
index fe1c8f0..64e0148 100644
--- a/savedstate/savedstate/api/current.txt
+++ b/savedstate/savedstate/api/current.txt
@@ -13,8 +13,11 @@
   @kotlin.jvm.JvmInline public final value class SavedStateReader {
     ctor public SavedStateReader(android.os.Bundle source);
     method public inline operator boolean contains(String key);
+    method public boolean contentDeepEquals(android.os.Bundle other);
     method public inline boolean getBoolean(String key);
     method public inline boolean getBooleanOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Boolean> defaultValue);
+    method public inline char getChar(String key);
+    method public inline char getCharOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Character> defaultValue);
     method public inline double getDouble(String key);
     method public inline double getDoubleOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Double> defaultValue);
     method public inline float getFloat(String key);
@@ -37,6 +40,7 @@
     method public inline java.util.List<java.lang.String> getStringListOrElse(String key, kotlin.jvm.functions.Function0<? extends java.util.List<java.lang.String>> defaultValue);
     method public inline String getStringOrElse(String key, kotlin.jvm.functions.Function0<java.lang.String> defaultValue);
     method public inline boolean isEmpty();
+    method public inline boolean isNull(String key);
     method public inline int size();
     property public final android.os.Bundle source;
   }
@@ -84,11 +88,13 @@
     method public android.os.Bundle getSource();
     method public inline void putAll(android.os.Bundle values);
     method public inline void putBoolean(String key, boolean value);
+    method public inline void putChar(String key, char value);
     method public inline void putDouble(String key, double value);
     method public inline void putFloat(String key, float value);
     method public inline void putInt(String key, int value);
     method public inline void putIntList(String key, java.util.List<java.lang.Integer> values);
     method public inline void putLong(String key, long value);
+    method public inline void putNull(String key);
     method public inline <reified T extends android.os.Parcelable> void putParcelable(String key, T value);
     method public inline <reified T extends android.os.Parcelable> void putParcelableList(String key, java.util.List<? extends T> values);
     method public inline void putSavedState(String key, android.os.Bundle value);
@@ -99,7 +105,7 @@
   }
 
   public final class SavedState_androidKt {
-    method public static inline android.os.Bundle savedState(optional kotlin.jvm.functions.Function1<? super androidx.savedstate.SavedStateWriter,kotlin.Unit> block);
+    method public static inline android.os.Bundle savedState(optional java.util.Map<java.lang.String,? extends java.lang.Object?> initialState, optional kotlin.jvm.functions.Function1<? super androidx.savedstate.SavedStateWriter,kotlin.Unit> builderAction);
   }
 
   public final class ViewKt {
diff --git a/savedstate/savedstate/api/restricted_current.txt b/savedstate/savedstate/api/restricted_current.txt
index 47dcf78..ea3533a 100644
--- a/savedstate/savedstate/api/restricted_current.txt
+++ b/savedstate/savedstate/api/restricted_current.txt
@@ -13,8 +13,11 @@
   @kotlin.jvm.JvmInline public final value class SavedStateReader {
     ctor public SavedStateReader(android.os.Bundle source);
     method public inline operator boolean contains(String key);
+    method public boolean contentDeepEquals(android.os.Bundle other);
     method public inline boolean getBoolean(String key);
     method public inline boolean getBooleanOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Boolean> defaultValue);
+    method public inline char getChar(String key);
+    method public inline char getCharOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Character> defaultValue);
     method public inline double getDouble(String key);
     method public inline double getDoubleOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Double> defaultValue);
     method public inline float getFloat(String key);
@@ -41,10 +44,15 @@
     method public inline java.util.List<java.lang.String> getStringListOrElse(String key, kotlin.jvm.functions.Function0<? extends java.util.List<java.lang.String>> defaultValue);
     method public inline String getStringOrElse(String key, kotlin.jvm.functions.Function0<java.lang.String> defaultValue);
     method public inline boolean isEmpty();
+    method public inline boolean isNull(String key);
     method public inline int size();
     property public final android.os.Bundle source;
   }
 
+  public final class SavedStateReader_androidKt {
+    method @kotlin.PublishedApi internal static boolean contentDeepEquals(android.os.Bundle, android.os.Bundle other);
+  }
+
   public final class SavedStateRegistry {
     method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String key);
     method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String key);
@@ -88,11 +96,13 @@
     method public android.os.Bundle getSource();
     method public inline void putAll(android.os.Bundle values);
     method public inline void putBoolean(String key, boolean value);
+    method public inline void putChar(String key, char value);
     method public inline void putDouble(String key, double value);
     method public inline void putFloat(String key, float value);
     method public inline void putInt(String key, int value);
     method public inline void putIntList(String key, java.util.List<java.lang.Integer> values);
     method public inline void putLong(String key, long value);
+    method public inline void putNull(String key);
     method public inline <reified T extends android.os.Parcelable> void putParcelable(String key, T value);
     method public inline <reified T extends android.os.Parcelable> void putParcelableList(String key, java.util.List<? extends T> values);
     method public inline void putSavedState(String key, android.os.Bundle value);
@@ -104,7 +114,7 @@
   }
 
   public final class SavedState_androidKt {
-    method public static inline android.os.Bundle savedState(optional kotlin.jvm.functions.Function1<? super androidx.savedstate.SavedStateWriter,kotlin.Unit> block);
+    method public static inline android.os.Bundle savedState(optional java.util.Map<java.lang.String,? extends java.lang.Object?> initialState, optional kotlin.jvm.functions.Function1<? super androidx.savedstate.SavedStateWriter,kotlin.Unit> builderAction);
   }
 
   public final class ViewKt {
@@ -124,6 +134,7 @@
     method public inline <reified T> T getValueFromSavedState(String key, kotlin.jvm.functions.Function0<? extends T?> currentValue, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean> contains, kotlin.jvm.functions.Function0<? extends T> defaultValue);
     method public inline Void keyNotFoundError(String key);
     field public static final boolean DEFAULT_BOOLEAN = false;
+    field public static final char DEFAULT_CHAR = 0; // 0x0000 '\u0000'
     field public static final double DEFAULT_DOUBLE = 0.0;
     field public static final float DEFAULT_FLOAT = 0.0f;
     field public static final int DEFAULT_INT = 0; // 0x0
diff --git a/savedstate/savedstate/bcv/native/current.txt b/savedstate/savedstate/bcv/native/current.txt
index 1a70510..a72f706 100644
--- a/savedstate/savedstate/bcv/native/current.txt
+++ b/savedstate/savedstate/bcv/native/current.txt
@@ -12,10 +12,10 @@
 }
 
 final class androidx.savedstate/SavedState { // androidx.savedstate/SavedState|null[0]
-    constructor <init>(kotlin.collections/MutableMap<kotlin/String, kotlin/Any> = ...) // androidx.savedstate/SavedState.<init>|<init>(kotlin.collections.MutableMap<kotlin.String,kotlin.Any>){}[0]
+    constructor <init>(kotlin.collections/MutableMap<kotlin/String, kotlin/Any?> = ...) // androidx.savedstate/SavedState.<init>|<init>(kotlin.collections.MutableMap<kotlin.String,kotlin.Any?>){}[0]
 
     final val map // androidx.savedstate/SavedState.map|{}map[0]
-        final fun <get-map>(): kotlin.collections/MutableMap<kotlin/String, kotlin/Any> // androidx.savedstate/SavedState.map.<get-map>|<get-map>(){}[0]
+        final fun <get-map>(): kotlin.collections/MutableMap<kotlin/String, kotlin/Any?> // androidx.savedstate/SavedState.map.<get-map>|<get-map>(){}[0]
 }
 
 final class androidx.savedstate/SavedStateRegistry { // androidx.savedstate/SavedStateRegistry|null[0]
@@ -51,6 +51,7 @@
     final val source // androidx.savedstate/SavedStateReader.source|{}source[0]
         final fun <get-source>(): androidx.savedstate/SavedState // androidx.savedstate/SavedStateReader.source.<get-source>|<get-source>(){}[0]
 
+    final fun contentDeepEquals(androidx.savedstate/SavedState): kotlin/Boolean // androidx.savedstate/SavedStateReader.contentDeepEquals|contentDeepEquals(androidx.savedstate.SavedState){}[0]
     final fun equals(kotlin/Any?): kotlin/Boolean // androidx.savedstate/SavedStateReader.equals|equals(kotlin.Any?){}[0]
     final fun hashCode(): kotlin/Int // androidx.savedstate/SavedStateReader.hashCode|hashCode(){}[0]
     final fun toString(): kotlin/String // androidx.savedstate/SavedStateReader.toString|toString(){}[0]
@@ -61,6 +62,8 @@
     final inline fun contains(kotlin/String): kotlin/Boolean // androidx.savedstate/SavedStateReader.contains|contains(kotlin.String){}[0]
     final inline fun getBoolean(kotlin/String): kotlin/Boolean // androidx.savedstate/SavedStateReader.getBoolean|getBoolean(kotlin.String){}[0]
     final inline fun getBooleanOrElse(kotlin/String, kotlin/Function0<kotlin/Boolean>): kotlin/Boolean // androidx.savedstate/SavedStateReader.getBooleanOrElse|getBooleanOrElse(kotlin.String;kotlin.Function0<kotlin.Boolean>){}[0]
+    final inline fun getChar(kotlin/String): kotlin/Char // androidx.savedstate/SavedStateReader.getChar|getChar(kotlin.String){}[0]
+    final inline fun getCharOrElse(kotlin/String, kotlin/Function0<kotlin/Char>): kotlin/Char // androidx.savedstate/SavedStateReader.getCharOrElse|getCharOrElse(kotlin.String;kotlin.Function0<kotlin.Char>){}[0]
     final inline fun getDouble(kotlin/String): kotlin/Double // androidx.savedstate/SavedStateReader.getDouble|getDouble(kotlin.String){}[0]
     final inline fun getDoubleOrElse(kotlin/String, kotlin/Function0<kotlin/Double>): kotlin/Double // androidx.savedstate/SavedStateReader.getDoubleOrElse|getDoubleOrElse(kotlin.String;kotlin.Function0<kotlin.Double>){}[0]
     final inline fun getFloat(kotlin/String): kotlin/Float // androidx.savedstate/SavedStateReader.getFloat|getFloat(kotlin.String){}[0]
@@ -78,6 +81,7 @@
     final inline fun getStringListOrElse(kotlin/String, kotlin/Function0<kotlin.collections/List<kotlin/String>>): kotlin.collections/List<kotlin/String> // androidx.savedstate/SavedStateReader.getStringListOrElse|getStringListOrElse(kotlin.String;kotlin.Function0<kotlin.collections.List<kotlin.String>>){}[0]
     final inline fun getStringOrElse(kotlin/String, kotlin/Function0<kotlin/String>): kotlin/String // androidx.savedstate/SavedStateReader.getStringOrElse|getStringOrElse(kotlin.String;kotlin.Function0<kotlin.String>){}[0]
     final inline fun isEmpty(): kotlin/Boolean // androidx.savedstate/SavedStateReader.isEmpty|isEmpty(){}[0]
+    final inline fun isNull(kotlin/String): kotlin/Boolean // androidx.savedstate/SavedStateReader.isNull|isNull(kotlin.String){}[0]
     final inline fun size(): kotlin/Int // androidx.savedstate/SavedStateReader.size|size(){}[0]
 }
 
@@ -93,11 +97,13 @@
     final inline fun clear() // androidx.savedstate/SavedStateWriter.clear|clear(){}[0]
     final inline fun putAll(androidx.savedstate/SavedState) // androidx.savedstate/SavedStateWriter.putAll|putAll(androidx.savedstate.SavedState){}[0]
     final inline fun putBoolean(kotlin/String, kotlin/Boolean) // androidx.savedstate/SavedStateWriter.putBoolean|putBoolean(kotlin.String;kotlin.Boolean){}[0]
+    final inline fun putChar(kotlin/String, kotlin/Char) // androidx.savedstate/SavedStateWriter.putChar|putChar(kotlin.String;kotlin.Char){}[0]
     final inline fun putDouble(kotlin/String, kotlin/Double) // androidx.savedstate/SavedStateWriter.putDouble|putDouble(kotlin.String;kotlin.Double){}[0]
     final inline fun putFloat(kotlin/String, kotlin/Float) // androidx.savedstate/SavedStateWriter.putFloat|putFloat(kotlin.String;kotlin.Float){}[0]
     final inline fun putInt(kotlin/String, kotlin/Int) // androidx.savedstate/SavedStateWriter.putInt|putInt(kotlin.String;kotlin.Int){}[0]
     final inline fun putIntList(kotlin/String, kotlin.collections/List<kotlin/Int>) // androidx.savedstate/SavedStateWriter.putIntList|putIntList(kotlin.String;kotlin.collections.List<kotlin.Int>){}[0]
     final inline fun putLong(kotlin/String, kotlin/Long) // androidx.savedstate/SavedStateWriter.putLong|putLong(kotlin.String;kotlin.Long){}[0]
+    final inline fun putNull(kotlin/String) // androidx.savedstate/SavedStateWriter.putNull|putNull(kotlin.String){}[0]
     final inline fun putSavedState(kotlin/String, androidx.savedstate/SavedState) // androidx.savedstate/SavedStateWriter.putSavedState|putSavedState(kotlin.String;androidx.savedstate.SavedState){}[0]
     final inline fun putString(kotlin/String, kotlin/String) // androidx.savedstate/SavedStateWriter.putString|putString(kotlin.String;kotlin.String){}[0]
     final inline fun putStringList(kotlin/String, kotlin.collections/List<kotlin/String>) // androidx.savedstate/SavedStateWriter.putStringList|putStringList(kotlin.String;kotlin.collections.List<kotlin.String>){}[0]
@@ -107,6 +113,8 @@
 final object androidx.savedstate.internal/SavedStateUtils { // androidx.savedstate.internal/SavedStateUtils|null[0]
     final const val DEFAULT_BOOLEAN // androidx.savedstate.internal/SavedStateUtils.DEFAULT_BOOLEAN|{}DEFAULT_BOOLEAN[0]
         final fun <get-DEFAULT_BOOLEAN>(): kotlin/Boolean // androidx.savedstate.internal/SavedStateUtils.DEFAULT_BOOLEAN.<get-DEFAULT_BOOLEAN>|<get-DEFAULT_BOOLEAN>(){}[0]
+    final const val DEFAULT_CHAR // androidx.savedstate.internal/SavedStateUtils.DEFAULT_CHAR|{}DEFAULT_CHAR[0]
+        final fun <get-DEFAULT_CHAR>(): kotlin/Char // androidx.savedstate.internal/SavedStateUtils.DEFAULT_CHAR.<get-DEFAULT_CHAR>|<get-DEFAULT_CHAR>(){}[0]
     final const val DEFAULT_DOUBLE // androidx.savedstate.internal/SavedStateUtils.DEFAULT_DOUBLE|{}DEFAULT_DOUBLE[0]
         final fun <get-DEFAULT_DOUBLE>(): kotlin/Double // androidx.savedstate.internal/SavedStateUtils.DEFAULT_DOUBLE.<get-DEFAULT_DOUBLE>|<get-DEFAULT_DOUBLE>(){}[0]
     final const val DEFAULT_FLOAT // androidx.savedstate.internal/SavedStateUtils.DEFAULT_FLOAT|{}DEFAULT_FLOAT[0]
@@ -126,4 +134,4 @@
 final inline fun <#A: kotlin/Any?> (androidx.savedstate/SavedState).androidx.savedstate/write(kotlin/Function1<androidx.savedstate/SavedStateWriter, #A>): #A // androidx.savedstate/write|[email protected](kotlin.Function1<androidx.savedstate.SavedStateWriter,0:0>){0§<kotlin.Any?>}[0]
 final inline fun <#A: kotlin/Any?> (androidx.savedstate/SavedStateReader).androidx.savedstate/write(kotlin/Function1<androidx.savedstate/SavedStateWriter, #A>): #A // androidx.savedstate/write|[email protected](kotlin.Function1<androidx.savedstate.SavedStateWriter,0:0>){0§<kotlin.Any?>}[0]
 final inline fun <#A: kotlin/Any?> (androidx.savedstate/SavedStateWriter).androidx.savedstate/read(kotlin/Function1<androidx.savedstate/SavedStateReader, #A>): #A // androidx.savedstate/read|[email protected](kotlin.Function1<androidx.savedstate.SavedStateReader,0:0>){0§<kotlin.Any?>}[0]
-final inline fun androidx.savedstate/savedState(kotlin/Function1<androidx.savedstate/SavedStateWriter, kotlin/Unit> = ...): androidx.savedstate/SavedState // androidx.savedstate/savedState|savedState(kotlin.Function1<androidx.savedstate.SavedStateWriter,kotlin.Unit>){}[0]
+final inline fun androidx.savedstate/savedState(kotlin.collections/Map<kotlin/String, kotlin/Any?> = ..., kotlin/Function1<androidx.savedstate/SavedStateWriter, kotlin/Unit> = ...): androidx.savedstate/SavedState // androidx.savedstate/savedState|savedState(kotlin.collections.Map<kotlin.String,kotlin.Any?>;kotlin.Function1<androidx.savedstate.SavedStateWriter,kotlin.Unit>){}[0]
diff --git a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedState.android.kt b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedState.android.kt
index 6d51126..b181e9b 100644
--- a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedState.android.kt
+++ b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedState.android.kt
@@ -14,9 +14,23 @@
  * limitations under the License.
  */
 
+@file:Suppress("NOTHING_TO_INLINE")
+
 package androidx.savedstate
 
+import androidx.core.os.bundleOf
+
 public actual typealias SavedState = android.os.Bundle
 
-public actual inline fun savedState(block: SavedStateWriter.() -> Unit): SavedState =
-    SavedState().apply { write(block) }
+public actual inline fun savedState(
+    initialState: Map<String, Any?>,
+    builderAction: SavedStateWriter.() -> Unit,
+): SavedState {
+    val pairs =
+        if (initialState.isEmpty()) {
+            emptyArray()
+        } else {
+            initialState.map { (key, value) -> key to value }.toTypedArray()
+        }
+    return bundleOf(*pairs).apply { write(builderAction) }
+}
diff --git a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt
index c17f0fa..430c4ef 100644
--- a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt
+++ b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt
@@ -33,7 +33,15 @@
     }
 
     actual inline fun getBooleanOrElse(key: String, defaultValue: () -> Boolean): Boolean {
-        return getSingleResultOrElse(key, defaultValue) { source.getBoolean(key) }
+        return getSingleResultOrElse(key, defaultValue) { source.getBoolean(key, defaultValue()) }
+    }
+
+    actual inline fun getChar(key: String): Char {
+        return getSingleResultOrThrow(key) { source.getChar(key, SavedStateUtils.DEFAULT_CHAR) }
+    }
+
+    actual inline fun getCharOrElse(key: String, defaultValue: () -> Char): Char {
+        return getSingleResultOrElse(key, defaultValue) { source.getChar(key, defaultValue()) }
     }
 
     actual inline fun getDouble(key: String): Double {
@@ -41,7 +49,7 @@
     }
 
     actual inline fun getDoubleOrElse(key: String, defaultValue: () -> Double): Double {
-        return getSingleResultOrElse(key, defaultValue) { source.getDouble(key) }
+        return getSingleResultOrElse(key, defaultValue) { source.getDouble(key, defaultValue()) }
     }
 
     actual inline fun getFloat(key: String): Float {
@@ -49,7 +57,7 @@
     }
 
     actual inline fun getFloatOrElse(key: String, defaultValue: () -> Float): Float {
-        return getSingleResultOrElse(key, defaultValue) { source.getFloat(key) }
+        return getSingleResultOrElse(key, defaultValue) { source.getFloat(key, defaultValue()) }
     }
 
     actual inline fun getInt(key: String): Int {
@@ -57,15 +65,15 @@
     }
 
     actual inline fun getIntOrElse(key: String, defaultValue: () -> Int): Int {
-        return getSingleResultOrElse(key, defaultValue) { source.getInt(key) }
+        return getSingleResultOrElse(key, defaultValue) { source.getInt(key, defaultValue()) }
     }
 
     actual inline fun getLong(key: String): Long {
-        return getSingleResultOrThrow(key) { source.getLong(key) }
+        return getSingleResultOrThrow(key) { source.getLong(key, SavedStateUtils.DEFAULT_LONG) }
     }
 
     actual inline fun getLongOrElse(key: String, defaultValue: () -> Long): Long {
-        return getSingleResultOrElse(key, defaultValue) { source.getLong(key) }
+        return getSingleResultOrElse(key, defaultValue) { source.getLong(key, defaultValue()) }
     }
 
     /**
@@ -102,7 +110,7 @@
     }
 
     actual inline fun getStringOrElse(key: String, defaultValue: () -> String): String {
-        return getSingleResultOrElse(key, defaultValue) { source.getString(key) }
+        return getSingleResultOrElse(key, defaultValue) { source.getString(key, defaultValue()) }
     }
 
     actual inline fun getIntList(key: String): List<Int> {
@@ -169,8 +177,17 @@
 
     actual inline fun isEmpty(): Boolean = source.isEmpty
 
+    actual inline fun isNull(key: String): Boolean {
+        // Using `getString` to check for `null` is unreliable as it returns null for type
+        // mismatches. To reliably determine if the value is actually `null`, we use the
+        // deprecated `Bundle.get`.
+        @Suppress("DEPRECATION") return contains(key) && source[key] == null
+    }
+
     actual inline operator fun contains(key: String): Boolean = source.containsKey(key)
 
+    actual fun contentDeepEquals(other: SavedState): Boolean = source.contentDeepEquals(other)
+
     @PublishedApi
     internal inline fun <reified T> getSingleResultOrThrow(
         key: String,
@@ -221,3 +238,23 @@
             defaultValue = { defaultValue() },
         )
 }
+
+@PublishedApi
+internal fun SavedState.contentDeepEquals(other: SavedState): Boolean {
+    if (this === other) return true
+    if (this.size() != other.size()) return false
+
+    for (k in this.keySet()) {
+        @Suppress("DEPRECATION") val v1 = this[k]
+        @Suppress("DEPRECATION") val v2 = other[k]
+
+        when {
+            v1 === v2 -> continue
+            v1 == null || v2 == null -> return false
+            v1 is SavedState && v2 is SavedState -> if (!v1.contentDeepEquals(v2)) return false
+            v1 is Array<*> && v2 is Array<*> -> if (!v1.contentDeepEquals(v2)) return false
+            else -> if (v1 != v2) return false
+        }
+    }
+    return true
+}
diff --git a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt
index 68df552..d0b5687 100644
--- a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt
+++ b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt
@@ -26,6 +26,10 @@
         source.putBoolean(key, value)
     }
 
+    actual inline fun putChar(key: String, value: Char) {
+        source.putChar(key, value)
+    }
+
     actual inline fun putDouble(key: String, value: Double) {
         source.putDouble(key, value)
     }
@@ -42,6 +46,10 @@
         source.putLong(key, value)
     }
 
+    actual inline fun putNull(key: String) {
+        source.putString(key, null)
+    }
+
     /**
      * Stores an [Parcelable] value associated with the specified key in the [SavedState].
      *
diff --git a/savedstate/savedstate/src/androidUnitTest/kotlin/androidx/savedstate/ParcelableSavedStateTest.android.kt b/savedstate/savedstate/src/androidUnitTest/kotlin/androidx/savedstate/ParcelableSavedStateTest.android.kt
index 48f76bf..73d9c8d 100644
--- a/savedstate/savedstate/src/androidUnitTest/kotlin/androidx/savedstate/ParcelableSavedStateTest.android.kt
+++ b/savedstate/savedstate/src/androidUnitTest/kotlin/androidx/savedstate/ParcelableSavedStateTest.android.kt
@@ -64,6 +64,14 @@
     }
 
     @Test
+    fun getParcelableOrElse_whenSet_differentType_returnsDefault() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getParcelableOrElse(KEY_1) { PARCELABLE_VALUE_1 } }
+
+        assertThat(actual).isEqualTo(PARCELABLE_VALUE_1)
+    }
+
+    @Test
     fun getParcelableList_whenSet_returns() {
         val expected = List(size = 5) { idx -> TestParcelable(idx) }
 
@@ -81,7 +89,7 @@
     }
 
     @Test
-    fun getListofParcelable_whenSet_differentType_throws() {
+    fun getList_whenSet_differentType_throws() {
         val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
 
         assertThrows<IllegalStateException> {
@@ -108,6 +116,14 @@
         assertThat(actual).isEqualTo(emptyList<TestParcelable>())
     }
 
+    @Test
+    fun getListOrElse_whenSet_differentType_throws() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getParcelableListOrElse(KEY_1) { emptyList() } }
+
+        assertThat(actual).isEqualTo(emptyList<Parcelable>())
+    }
+
     private companion object {
         const val KEY_1 = "KEY_1"
         val PARCELABLE_VALUE_1 = TestParcelable(value = Int.MIN_VALUE)
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedState.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedState.kt
index 710bdd0..2dd1c03 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedState.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedState.kt
@@ -31,8 +31,24 @@
  */
 public expect class SavedState
 
-/** Constructs an empty [SavedState] instance. */
-public expect inline fun savedState(block: SavedStateWriter.() -> Unit = {}): SavedState
+/**
+ * Builds a new [SavedState] with the specified [initialState], given as a [Map] of [String] keys
+ * and [Any] value.
+ *
+ * Allows further modification of the state using the [builderAction].
+ *
+ * **IMPORTANT:** The [SavedStateWriter] passed as a receiver to the [builderAction] is valid only
+ * inside that function. Using it outside of the function may produce an unspecified behavior.
+ *
+ * @param initialState An initial map of key-value pairs to populate the state. Defaults to an empty
+ *   map.
+ * @param builderAction A lambda function with a [SavedStateWriter] receiver to modify the state.
+ * @return A [SavedState] instance containing the initialized key-value pairs.
+ */
+public expect inline fun savedState(
+    initialState: Map<String, Any?> = emptyMap(),
+    builderAction: SavedStateWriter.() -> Unit = {},
+): SavedState
 
 /** Creates a new [SavedStateReader] for the [SavedState]. */
 public fun SavedState.reader(): SavedStateReader = SavedStateReader(source = this)
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt
index e3f37ac..cd7cc0a 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt
@@ -52,6 +52,27 @@
     public inline fun getBooleanOrElse(key: String, defaultValue: () -> Boolean): Boolean
 
     /**
+     * Retrieves a [Char] value associated with the specified [key]. Throws an
+     * [IllegalStateException] if the [key] doesn't exist.
+     *
+     * @param key The [key] to retrieve the value for.
+     * @return The [Char] value associated with the [key].
+     * @throws IllegalStateException If the [key] is not found.
+     */
+    public inline fun getChar(key: String): Char
+
+    /**
+     * Retrieves a [Char] value associated with the specified [key], or a default value if the [key]
+     * doesn't exist.
+     *
+     * @param key The [key] to retrieve the value for.
+     * @param defaultValue A function providing the default value if the [key] is not found.
+     * @return The [Char] value associated with the [key], or the default value if the [key] is not
+     *   found.
+     */
+    public inline fun getCharOrElse(key: String, defaultValue: () -> Char): Char
+
+    /**
      * Retrieves a [Double] value associated with the specified [key]. Throws an
      * [IllegalStateException] if the [key] doesn't exist.
      *
@@ -239,10 +260,31 @@
     public inline fun isEmpty(): Boolean
 
     /**
+     * Checks if the [SavedState] contains a null reference for the specified [key].
+     *
+     * @param key The [key] to check for.
+     * @return `true` if the [SavedState] contains a null reference for the [key], `false`
+     *   otherwise.
+     */
+    public inline fun isNull(key: String): Boolean
+
+    /**
      * Checks if the [SavedState] contains the specified [key].
      *
      * @param key The [key] to check for.
      * @return `true` if the [SavedState] contains the [key], `false` otherwise.
      */
     public inline operator fun contains(key: String): Boolean
+
+    /**
+     * Checks if the two specified [SavedState] are *deeply* equal to one another.
+     *
+     * Two [SavedState] are considered deeply equal if they have the same size, and elements at
+     * corresponding keys are deeply equal. That is, if two corresponding elements are nested
+     * [SavedState], they are also compared deeply.
+     *
+     * @param other the object to compare deeply with this.
+     * @return `true` if the two are deeply equal, `false` otherwise.
+     */
+    public fun contentDeepEquals(other: SavedState): Boolean
 }
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt
index bf7aff6..f4d7c44 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt
@@ -38,6 +38,8 @@
      */
     public inline fun putBoolean(key: String, value: Boolean)
 
+    public inline fun putChar(key: String, value: Char)
+
     /**
      * Stores a double value associated with the specified key in the [SavedState].
      *
@@ -71,6 +73,13 @@
     public inline fun putLong(key: String, value: Long)
 
     /**
+     * Stores a null reference associated with the specified key in the [SavedState].
+     *
+     * @param key The key to associate the null reference.
+     */
+    public inline fun putNull(key: String)
+
+    /**
      * Stores a string value associated with the specified key in the [SavedState].
      *
      * @param key The key to associate the value with.
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt
index bf602bd..44326b9 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt
@@ -20,6 +20,7 @@
 internal object SavedStateUtils {
 
     const val DEFAULT_BOOLEAN = false
+    const val DEFAULT_CHAR: Char = 0.toChar()
     const val DEFAULT_FLOAT = 0F
     const val DEFAULT_DOUBLE = 0.0
     const val DEFAULT_INT = 0
diff --git a/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt b/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt
index b40f557..8991f3b 100644
--- a/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt
+++ b/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt
@@ -95,6 +95,89 @@
         assertThat(underTest.read { isEmpty() }).isTrue()
     }
 
+    @Test
+    fun contentDeepEquals_withEqualContent_returnsTrue() {
+        val sharedState = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+        }
+        val state1 = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+        val state2 = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+
+        val contentDeepEquals = state1.read { contentDeepEquals(state2) }
+
+        assertThat(contentDeepEquals).isTrue()
+    }
+
+    @Test
+    fun contentDeepEquals_withMissingKey_returnsFalse() {
+        val sharedState = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+        }
+        val state1 = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+        val state2 = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+
+        val contentDeepEquals = state1.read { contentDeepEquals(state2) }
+
+        assertThat(contentDeepEquals).isFalse()
+    }
+
+    @Test
+    fun contentDeepEquals_withDifferentContent_returnsFalse() {
+        val sharedState = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+        }
+        val state1 = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+        val state2 = savedState {
+            putFloat(KEY_1, Float.MAX_VALUE)
+            putFloat(KEY_2, Float.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+
+        val contentDeepEquals = state1.read { contentDeepEquals(state2) }
+
+        assertThat(contentDeepEquals).isFalse()
+    }
+
+    @Test
+    fun contentDeepEquals_withEmptyContent_returnsFalse() {
+        val sharedState = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+        }
+        val state1 = savedState {
+            putInt(KEY_1, Int.MAX_VALUE)
+            putInt(KEY_2, Int.MAX_VALUE)
+            putSavedState(KEY_3, sharedState)
+        }
+        val state2 = savedState()
+
+        val contentDeepEquals = state1.read { contentDeepEquals(state2) }
+
+        assertThat(contentDeepEquals).isFalse()
+    }
+
     // region getters and setters
     @Test
     fun getBoolean_whenSet_returns() {
@@ -131,9 +214,61 @@
 
     @Test
     fun getBooleanOrElse_whenNotSet_returnsElse() {
-        val actual = savedState().read { getBooleanOrElse(KEY_1) { false } }
+        val actual = savedState().read { getBooleanOrElse(KEY_1) { true } }
 
-        assertThat(actual).isFalse()
+        assertThat(actual).isTrue()
+    }
+
+    @Test
+    fun getBooleanOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getBooleanOrElse(KEY_1) { true } }
+
+        assertThat(actual).isTrue()
+    }
+
+    @Test
+    fun getChar_whenSet_returns() {
+        val underTest = savedState { putChar(KEY_1, Char.MAX_VALUE) }
+        val actual = underTest.read { getChar(KEY_1) }
+
+        assertThat(actual).isEqualTo(Char.MAX_VALUE)
+    }
+
+    @Test
+    fun getChar_whenNotSet_throws() {
+        assertThrows<IllegalStateException> { savedState().read { getChar(KEY_1) } }
+    }
+
+    @Test
+    fun getChar_whenSet_differentType_returnsDefault() {
+        val underTest = savedState { putInt(KEY_1, Int.MIN_VALUE) }
+        val actual = underTest.read { getChar(KEY_1) }
+
+        assertThat(actual).isEqualTo(SavedStateUtils.DEFAULT_CHAR)
+    }
+
+    @Test
+    fun getCharOrElse_whenSet_returns() {
+        val underTest = savedState { putChar(KEY_1, Char.MAX_VALUE) }
+        val actual = underTest.read { getCharOrElse(KEY_1) { Char.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Char.MAX_VALUE)
+    }
+
+    @Test
+    fun getCharOrElse_whenNotSet_returnsElse() {
+        val actual = savedState().read { getCharOrElse(KEY_1) { Char.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Char.MIN_VALUE)
+    }
+
+    @Test
+    fun getCharOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getCharOrElse(KEY_1) { Char.MAX_VALUE } }
+
+        assertThat(actual).isEqualTo(Char.MAX_VALUE)
     }
 
     @Test
@@ -173,6 +308,14 @@
     }
 
     @Test
+    fun getDoubleOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getDoubleOrElse(KEY_1) { Double.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Double.MIN_VALUE)
+    }
+
+    @Test
     fun getFloat_whenSet_returns() {
         val underTest = savedState { putFloat(KEY_1, Float.MAX_VALUE) }
         val actual = underTest.read { getFloat(KEY_1) }
@@ -209,6 +352,14 @@
     }
 
     @Test
+    fun getFloatOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getFloatOrElse(KEY_1) { Float.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Float.MIN_VALUE)
+    }
+
+    @Test
     fun getInt_whenSet_returns() {
         val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
         val actual = underTest.read { getInt(KEY_1) }
@@ -245,6 +396,14 @@
     }
 
     @Test
+    fun getIntOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putBoolean(KEY_1, false) }
+        val actual = underTest.read { getIntOrElse(KEY_1) { Int.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Int.MIN_VALUE)
+    }
+
+    @Test
     fun getLong_whenSet_returns() {
         val underTest = savedState { putLong(KEY_1, Long.MAX_VALUE) }
         val actual = underTest.read { getLong(KEY_1) }
@@ -281,6 +440,38 @@
     }
 
     @Test
+    fun getLongOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putBoolean(KEY_1, false) }
+        val actual = underTest.read { getLongOrElse(KEY_1) { Long.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Long.MIN_VALUE)
+    }
+
+    @Test
+    fun putNull_whenSet_returnsTrue() {
+        val underTest = savedState { putNull(KEY_1) }
+        val actual = underTest.read { isNull(KEY_1) }
+
+        assertThat(actual).isTrue()
+    }
+
+    @Test
+    fun getNull_whenSet_nonNull_returnsFalse() {
+        val underTest = savedState { putBoolean(KEY_1, true) }
+        val actual = underTest.read { isNull(KEY_1) }
+
+        assertThat(actual).isFalse()
+    }
+
+    @Test
+    fun putNull_whenNotSet_returnsFalse() {
+        val underTest = savedState()
+        val actual = underTest.read { isNull(KEY_1) }
+
+        assertThat(actual).isFalse()
+    }
+
+    @Test
     fun getString_whenSet_returns() {
         val underTest = savedState { putString(KEY_1, STRING_VALUE) }
         val actual = underTest.read { getString(KEY_1) }
@@ -316,6 +507,15 @@
     }
 
     @Test
+    fun getStringOrElse_whenSet_differentType_returnsElse() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+
+        val actual = underTest.read { getStringOrElse(KEY_1) { STRING_VALUE } }
+
+        assertThat(actual).isEqualTo(STRING_VALUE)
+    }
+
+    @Test
     fun getIntList_whenSet_returns() {
         val expected = List(size = 5) { idx -> idx }
 
@@ -355,6 +555,16 @@
     }
 
     @Test
+    fun getIntOrElseList_whenSet_differentType_returnsElse() {
+        val expected = Int.MAX_VALUE
+
+        val underTest = savedState { putInt(KEY_1, expected) }
+        val actual = underTest.read { getIntListOrElse(KEY_1) { emptyList() } }
+
+        assertThat(actual).isEqualTo(emptyList<Int>())
+    }
+
+    @Test
     fun getStringList_whenSet_returns() {
         val underTest = savedState { putStringList(KEY_1, LIST_STRING_VALUE) }
         val actual = underTest.read { getStringList(KEY_1) }
@@ -392,6 +602,16 @@
     }
 
     @Test
+    fun getStringListOrElse_whenSet_differentType_returnsElse() {
+        val expected = Int.MAX_VALUE
+
+        val underTest = savedState { putInt(KEY_1, expected) }
+        val actual = underTest.read { getStringListOrElse(KEY_1) { emptyList() } }
+
+        assertThat(actual).isEqualTo(emptyList<String>())
+    }
+
+    @Test
     fun getSavedState_whenSet_returns() {
         val underTest = savedState { putSavedState(KEY_1, SAVED_STATE_VALUE) }
         val actual = underTest.read { getSavedState(KEY_1) }
@@ -405,6 +625,13 @@
     }
 
     @Test
+    fun getSavedState_whenSet_differentType_throws() {
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+
+        assertThrows<IllegalStateException> { underTest.read { getSavedState(KEY_1) } }
+    }
+
+    @Test
     fun getSavedStateOrElse_whenSet_returns() {
         val underTest = savedState { putSavedState(KEY_1, SAVED_STATE_VALUE) }
         val actual = underTest.read { getSavedStateOrElse(KEY_1) { savedState() } }
@@ -422,6 +649,16 @@
     }
 
     @Test
+    fun getSavedStateOrElse_whenSet_differentType_returnsElse() {
+        val expected = savedState()
+
+        val underTest = savedState { putInt(KEY_1, Int.MAX_VALUE) }
+        val actual = underTest.read { getSavedStateOrElse(KEY_1) { expected } }
+
+        assertThat(actual).isEqualTo(expected)
+    }
+
+    @Test
     fun putAll() {
         val previousState = savedState { putInt(KEY_1, Int.MAX_VALUE) }
 
@@ -436,6 +673,7 @@
     private companion object {
         const val KEY_1 = "KEY_1"
         const val KEY_2 = "KEY_2"
+        const val KEY_3 = "KEY_3"
         const val STRING_VALUE = "string-value"
         val LIST_INT_VALUE = List(size = 5) { idx -> idx }
         val LIST_STRING_VALUE = List(size = 5) { idx -> "index=$idx" }
diff --git a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedState.nonAndroid.kt b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedState.nonAndroid.kt
index 127e516..c8e4d106 100644
--- a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedState.nonAndroid.kt
+++ b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedState.nonAndroid.kt
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
+@file:Suppress("NOTHING_TO_INLINE")
+
 package androidx.savedstate
 
 public actual class SavedState
 @PublishedApi
-internal constructor(@PublishedApi internal val map: MutableMap<String, Any> = mutableMapOf())
+internal constructor(@PublishedApi internal val map: MutableMap<String, Any?> = mutableMapOf())
 
-actual inline fun savedState(block: SavedStateWriter.() -> Unit): SavedState =
-    SavedState().apply { write(block) }
+actual inline fun savedState(
+    initialState: Map<String, Any?>,
+    builderAction: SavedStateWriter.() -> Unit,
+): SavedState = SavedState(initialState.toMutableMap()).apply { write(builderAction) }
diff --git a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt
index 01e3cd9..f3f1797 100644
--- a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt
+++ b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt
@@ -31,41 +31,37 @@
         }
 
     actual inline fun getBooleanOrElse(key: String, defaultValue: () -> Boolean): Boolean =
-        getSingleResultOrElse(key, defaultValue) {
-            source.map[key] as? Boolean ?: SavedStateUtils.DEFAULT_BOOLEAN
-        }
+        getSingleResultOrElse(key, defaultValue) { source.map[key] as? Boolean }
+
+    actual inline fun getChar(key: String): Char =
+        getSingleResultOrThrow(key) { source.map[key] as? Char ?: SavedStateUtils.DEFAULT_CHAR }
+
+    actual inline fun getCharOrElse(key: String, defaultValue: () -> Char): Char =
+        getSingleResultOrElse(key, defaultValue) { source.map[key] as? Char }
 
     actual inline fun getDouble(key: String): Double =
         getSingleResultOrThrow(key) { source.map[key] as? Double ?: SavedStateUtils.DEFAULT_DOUBLE }
 
     actual inline fun getDoubleOrElse(key: String, defaultValue: () -> Double): Double =
-        getSingleResultOrElse(key, defaultValue) {
-            source.map[key] as? Double ?: SavedStateUtils.DEFAULT_DOUBLE
-        }
+        getSingleResultOrElse(key, defaultValue) { source.map[key] as? Double }
 
     actual inline fun getFloat(key: String): Float =
         getSingleResultOrThrow(key) { source.map[key] as? Float ?: SavedStateUtils.DEFAULT_FLOAT }
 
     actual inline fun getFloatOrElse(key: String, defaultValue: () -> Float): Float =
-        getSingleResultOrElse(key, defaultValue) {
-            source.map[key] as? Float ?: SavedStateUtils.DEFAULT_FLOAT
-        }
+        getSingleResultOrElse(key, defaultValue) { source.map[key] as? Float }
 
     actual inline fun getInt(key: String): Int =
         getSingleResultOrThrow(key) { source.map[key] as? Int ?: SavedStateUtils.DEFAULT_INT }
 
     actual inline fun getIntOrElse(key: String, defaultValue: () -> Int): Int =
-        getSingleResultOrElse(key, defaultValue) {
-            source.map[key] as? Int ?: SavedStateUtils.DEFAULT_INT
-        }
+        getSingleResultOrElse(key, defaultValue) { source.map[key] as? Int }
 
     actual inline fun getLong(key: String): Long =
         getSingleResultOrThrow(key) { source.map[key] as? Long ?: SavedStateUtils.DEFAULT_LONG }
 
     actual inline fun getLongOrElse(key: String, defaultValue: () -> Long): Long =
-        getSingleResultOrElse(key, defaultValue) {
-            source.map[key] as? Long ?: SavedStateUtils.DEFAULT_LONG
-        }
+        getSingleResultOrElse(key, defaultValue) { source.map[key] as? Long }
 
     actual inline fun getString(key: String): String =
         getSingleResultOrThrow(key) { source.map[key] as? String }
@@ -110,6 +106,10 @@
         return source.map.isEmpty()
     }
 
+    actual inline fun isNull(key: String): Boolean {
+        return contains(key) && source.map[key] == null
+    }
+
     actual inline operator fun contains(key: String): Boolean {
         return source.map.containsKey(key)
     }
@@ -163,4 +163,9 @@
             currentValue = { currentValue() },
             defaultValue = { defaultValue() },
         )
+
+    actual fun contentDeepEquals(other: SavedState): Boolean {
+        // Map implements `equals` as a content deep, there is no need to do anything else.
+        return source.map == other.map
+    }
 }
diff --git a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt
index 4b614d6..8d60484 100644
--- a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt
+++ b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt
@@ -26,6 +26,10 @@
         source.map[key] = value
     }
 
+    actual inline fun putChar(key: String, value: Char) {
+        source.map[key] = value
+    }
+
     actual inline fun putDouble(key: String, value: Double) {
         source.map[key] = value
     }
@@ -42,6 +46,10 @@
         source.map[key] = value
     }
 
+    actual inline fun putNull(key: String) {
+        source.map[key] = null
+    }
+
     actual inline fun putString(key: String, value: String) {
         source.map[key] = value
     }
diff --git a/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt b/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt
index 73796ac..b26e8b5 100644
--- a/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt
+++ b/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.os.Build
 import android.os.Bundle
+import androidx.security.state.SecurityPatchState.DateBasedSecurityPatchLevel
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
@@ -140,4 +141,17 @@
         val bundle = securityStateManager.getGlobalSecurityState()
         assertFalse(bundle.containsKey("vendor_spl"))
     }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testGetGlobalSecurityState_withGoogleModules_doesNotThrow() {
+        if (!Build.MANUFACTURER.equals("Google", ignoreCase = true)) {
+            return // Skip this test on non-Google devices.
+        }
+        val bundle =
+            securityStateManager.getGlobalSecurityState("com.google.android.modulemetadata")
+        DateBasedSecurityPatchLevel.fromString(
+            bundle.getString("com.google.android.modulemetadata")!!
+        )
+    }
 }
diff --git a/security/security-state/src/main/AndroidManifest.xml b/security/security-state/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4103b9d0
--- /dev/null
+++ b/security/security-state/src/main/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <queries>
+        <package android:name="com.google.android.modulemetadata" />
+        <package android:name="com.google.mainline.telemetry" />
+        <package android:name="com.google.mainline.adservices" />
+        <package android:name="com.google.mainline.go.primary" />
+        <package android:name="com.google.mainline.go.telemetry" />
+    </queries>
+</manifest>
\ No newline at end of file
diff --git a/sqlite/integration-tests/driver-conformance-test/build.gradle b/sqlite/integration-tests/driver-conformance-test/build.gradle
index fd7b912..a2dc3f9 100644
--- a/sqlite/integration-tests/driver-conformance-test/build.gradle
+++ b/sqlite/integration-tests/driver-conformance-test/build.gradle
@@ -26,11 +26,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.sqlite.driver.test"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     ios()
     jvm()
     linux()
@@ -78,9 +87,6 @@
     }
 }
 
-android {
-    namespace "androidx.sqlite.driver.test"
-}
 
 androidx {
     name = "SQLite Driver Coformance Base Tests"
diff --git a/sqlite/sqlite-framework/build.gradle b/sqlite/sqlite-framework/build.gradle
index 411b332f..c9fff30 100644
--- a/sqlite/sqlite-framework/build.gradle
+++ b/sqlite/sqlite-framework/build.gradle
@@ -29,10 +29,8 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
-
 configurations {
     // Configuration for resolving shared archive file of androidx's SQLite compilation
     sqliteSharedArchive {
@@ -53,7 +51,17 @@
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.sqlite.db.framework"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     ios() {
         // Link to sqlite3 available in iOS
         binaries.configureEach {
@@ -148,6 +156,3 @@
     description = "The implementation of SQLite library using the framework code."
 }
 
-android {
-    namespace "androidx.sqlite.db.framework"
-}
diff --git a/sqlite/sqlite/build.gradle b/sqlite/sqlite/build.gradle
index 3c4a438..43cf644 100644
--- a/sqlite/sqlite/build.gradle
+++ b/sqlite/sqlite/build.gradle
@@ -28,12 +28,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
-
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.sqlite.db"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     ios()
     jvm()
     linux()
@@ -81,9 +89,6 @@
     }
 }
 
-android {
-    namespace "androidx.sqlite.db"
-}
 
 androidx {
     name = "SQLite"
diff --git a/testutils/testutils-lifecycle/build.gradle b/testutils/testutils-lifecycle/build.gradle
index 9d088a1..4408879 100644
--- a/testutils/testutils-lifecycle/build.gradle
+++ b/testutils/testutils-lifecycle/build.gradle
@@ -27,11 +27,20 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
-    android()
+    androidLibrary {
+        namespace = "androidx.testutils.lifecycle"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+        withAndroidTestOnJvmBuilder {
+            it.defaultSourceSetName = "androidUnitTest"
+        }
+    }
     desktop()
     mac()
     linux()
@@ -66,9 +75,6 @@
     }
 }
 
-android {
-    namespace "androidx.testutils.lifecycle"
-}
 
 androidx {
     type = LibraryType.INTERNAL_TEST_LIBRARY
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt
index 78cdb6f..4ef9228 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt
@@ -351,14 +351,13 @@
             edgeSwipeState: State<EdgeSwipeState>
         ): NestedScrollConnection =
             object : NestedScrollConnection {
-                @Suppress("DEPRECATION") // b/327155912
                 override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                     val delta = available.x
                     // If swipeState = SwipeState.SWIPING_TO_DISMISS - perform swipeToDismiss
                     // drag and consume everything
                     return if (
                         edgeSwipeState.value == EdgeSwipeState.SwipingToDismiss &&
-                            source == NestedScrollSource.Drag
+                            source == NestedScrollSource.UserInput
                     ) {
                         dispatchRawDelta(delta)
                         available
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt
index c4ffe24..2f5c10d 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt
@@ -477,7 +477,6 @@
      *
      * @return The delta the consumed by the [SwipeableV2State]
      */
-    @Suppress("DEPRECATION") // b/327155912
     fun dispatchRawDelta(delta: Float): Float {
         var remainingDelta = delta
 
@@ -486,7 +485,7 @@
             val consumedByParent =
                 nestedScrollDispatcher.dispatchPreScroll(
                     available = offsetWithOrientation(remainingDelta),
-                    source = NestedScrollSource.Drag
+                    source = NestedScrollSource.UserInput
                 )
             remainingDelta -= (consumedByParent.x + consumedByParent.y)
         }
@@ -503,7 +502,7 @@
                 nestedScrollDispatcher.dispatchPostScroll(
                     consumed = offsetWithOrientation(deltaToConsume),
                     available = offsetWithOrientation(delta - deltaToConsume),
-                    source = NestedScrollSource.Drag
+                    source = NestedScrollSource.UserInput
                 )
             remainingDelta -= (deltaToConsume + consumedDelta.x + consumedDelta.y)
         }
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
index aa1b486..988ad1c 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
@@ -20,6 +20,7 @@
 import androidx.compose.animation.animateColorAsState
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.CubicBezierEasing
+import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.animation.core.Transition
 import androidx.compose.animation.core.TweenSpec
 import androidx.compose.animation.core.animateFloat
@@ -87,7 +88,7 @@
     enabled: Boolean,
     onCheckedChange: ((Boolean) -> Unit)?,
     interactionSource: MutableInteractionSource?,
-    progressAnimationSpec: TweenSpec<Float>,
+    progressAnimationSpec: FiniteAnimationSpec<Float>,
     drawBox: FunctionDrawBox,
     width: Dp,
     height: Dp,
@@ -274,6 +275,59 @@
     width: Dp,
     height: Dp,
     ripple: Indication
+) =
+    RadioButton(
+        modifier = modifier,
+        selected = selected,
+        enabled = enabled,
+        ringColor = ringColor,
+        dotColor = dotColor,
+        onClick = onClick,
+        interactionSource = interactionSource,
+        dotRadiusAnimationSpec = tween(dotRadiusProgressDuration(selected), 0, easing),
+        dotAlphaAnimationSpec = tween(dotAlphaProgressDuration, dotAlphaProgressDelay, easing),
+        width = width,
+        height = height,
+        ripple = ripple
+    )
+
+/**
+ * [RadioButton] provides an animated radio button for use in material APIs.
+ *
+ * @param modifier Modifier to be applied to the radio button. This can be used to provide a content
+ *   description for accessibility.
+ * @param selected Boolean flag indicating whether this radio button is currently toggled on.
+ * @param enabled Boolean flag indicating the enabled state of the [RadioButton] (affects the
+ *   color).
+ * @param ringColor Composable lambda from which the ring color of the radio button will be
+ *   obtained.
+ * @param dotColor Composable lambda from which the dot color of the radio button will be obtained.
+ * @param onClick Callback to be invoked when RadioButton is clicked. If null, then this is passive
+ *   and relies entirely on a higher-level component to control the state.
+ * @param interactionSource When also providing [onClick], the [MutableInteractionSource]
+ *   representing the stream of [Interaction]s for the "toggleable" tap area - can be used to
+ *   customise the appearance / behavior of the RadioButton.
+ * @param dotRadiusAnimationSpec Animation spec of the dot radius progress animation.
+ * @param dotAlphaAnimationSpec Animation spec of the dot alpha progress animation.
+ * @param width Width of the radio button.
+ * @param height Height of the radio button.
+ * @param ripple Ripple used for the radio button.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@Composable
+fun RadioButton(
+    modifier: Modifier,
+    selected: Boolean,
+    enabled: Boolean,
+    ringColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color>,
+    dotColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color>,
+    onClick: (() -> Unit)?,
+    interactionSource: MutableInteractionSource?,
+    dotRadiusAnimationSpec: FiniteAnimationSpec<Float>,
+    dotAlphaAnimationSpec: FiniteAnimationSpec<Float>,
+    width: Dp,
+    height: Dp,
+    ripple: Indication
 ) {
     val targetState = if (selected) SelectionStage.Checked else SelectionStage.Unchecked
     val transition = updateTransition(targetState)
@@ -286,7 +340,7 @@
         animateProgress(
             transition = transition,
             label = "dot-radius",
-            animationSpec = tween(dotRadiusProgressDuration(selected), 0, easing)
+            animationSpec = dotRadiusAnimationSpec
         )
     // Animation of the dot alpha only happens when toggling On to Off.
     val dotAlphaProgress =
@@ -294,7 +348,7 @@
             animateProgress(
                 transition = transition,
                 label = "dot-alpha",
-                animationSpec = tween(dotAlphaProgressDuration, dotAlphaProgressDelay, easing)
+                animationSpec = dotAlphaAnimationSpec
             )
         else null
 
@@ -426,7 +480,7 @@
 private fun animateProgress(
     transition: Transition<SelectionStage>,
     label: String,
-    animationSpec: TweenSpec<Float>,
+    animationSpec: FiniteAnimationSpec<Float>,
 ) =
     transition.animateFloat(transitionSpec = { animationSpec }, label = label) {
         when (it) {
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt
index f28182d..a2e882f 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt
@@ -424,10 +424,11 @@
                         dismissCounter++
                         show.value = false
                     },
-                    durationMillis = 100
+                    durationMillis = 300
                 )
             }
         }
+        rule.waitForIdle()
         rule.waitUntilDoesNotExist(hasTestTag(TEST_TAG))
         assertEquals(1, dismissCounter)
     }
diff --git a/wear/compose/compose-material3/api/current.txt b/wear/compose/compose-material3/api/current.txt
index dc5e915..178be84 100644
--- a/wear/compose/compose-material3/api/current.txt
+++ b/wear/compose/compose-material3/api/current.txt
@@ -851,11 +851,11 @@
 
   public final class PlaceholderDefaults {
     method public androidx.compose.ui.graphics.Shape getShape();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter painterWithPlaceholderOverlayBackgroundBrush(androidx.wear.compose.material3.PlaceholderState placeholderState, androidx.compose.ui.graphics.painter.Painter painter, optional long color);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter painterWithPlaceholderOverlayBackgroundBrush(androidx.wear.compose.material3.PlaceholderState placeholderState, androidx.compose.ui.graphics.painter.Painter originalPainter, optional long color);
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter placeholderBackgroundBrush(androidx.wear.compose.material3.PlaceholderState placeholderState, optional long color);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ButtonColors placeholderButtonColors(androidx.wear.compose.material3.ButtonColors originalButtonColors, androidx.wear.compose.material3.PlaceholderState placeholderState, optional long color);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ButtonColors placeholderButtonColors(androidx.wear.compose.material3.PlaceholderState placeholderState, optional long color);
-    property public final androidx.compose.ui.graphics.Shape shape;
+    property public final androidx.compose.ui.graphics.Shape Shape;
     field public static final androidx.wear.compose.material3.PlaceholderDefaults INSTANCE;
   }
 
@@ -866,13 +866,11 @@
   }
 
   @androidx.compose.runtime.Stable public final class PlaceholderState {
-    method public float getPlaceholderProgression();
-    method public boolean isShowContent();
-    method public boolean isWipeOff();
-    method public suspend Object? startPlaceholderAnimation(kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    property public final boolean isShowContent;
-    property public final boolean isWipeOff;
-    property public final float placeholderProgression;
+    method public suspend Object? animatePlaceholder(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public boolean isHidden();
+    method public boolean isWipingOff();
+    property public final boolean isHidden;
+    property public final boolean isWipingOff;
   }
 
   public final class ProgressIndicatorColors {
diff --git a/wear/compose/compose-material3/api/restricted_current.txt b/wear/compose/compose-material3/api/restricted_current.txt
index dc5e915..178be84 100644
--- a/wear/compose/compose-material3/api/restricted_current.txt
+++ b/wear/compose/compose-material3/api/restricted_current.txt
@@ -851,11 +851,11 @@
 
   public final class PlaceholderDefaults {
     method public androidx.compose.ui.graphics.Shape getShape();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter painterWithPlaceholderOverlayBackgroundBrush(androidx.wear.compose.material3.PlaceholderState placeholderState, androidx.compose.ui.graphics.painter.Painter painter, optional long color);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter painterWithPlaceholderOverlayBackgroundBrush(androidx.wear.compose.material3.PlaceholderState placeholderState, androidx.compose.ui.graphics.painter.Painter originalPainter, optional long color);
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter placeholderBackgroundBrush(androidx.wear.compose.material3.PlaceholderState placeholderState, optional long color);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ButtonColors placeholderButtonColors(androidx.wear.compose.material3.ButtonColors originalButtonColors, androidx.wear.compose.material3.PlaceholderState placeholderState, optional long color);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ButtonColors placeholderButtonColors(androidx.wear.compose.material3.PlaceholderState placeholderState, optional long color);
-    property public final androidx.compose.ui.graphics.Shape shape;
+    property public final androidx.compose.ui.graphics.Shape Shape;
     field public static final androidx.wear.compose.material3.PlaceholderDefaults INSTANCE;
   }
 
@@ -866,13 +866,11 @@
   }
 
   @androidx.compose.runtime.Stable public final class PlaceholderState {
-    method public float getPlaceholderProgression();
-    method public boolean isShowContent();
-    method public boolean isWipeOff();
-    method public suspend Object? startPlaceholderAnimation(kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    property public final boolean isShowContent;
-    property public final boolean isWipeOff;
-    property public final float placeholderProgression;
+    method public suspend Object? animatePlaceholder(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public boolean isHidden();
+    method public boolean isWipingOff();
+    property public final boolean isHidden;
+    property public final boolean isWipingOff;
   }
 
   public final class ProgressIndicatorColors {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt
index 9ea719e..621a163 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt
@@ -29,6 +29,7 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
 import androidx.wear.compose.integration.demos.common.ComposableDemo
 import androidx.wear.compose.material3.Button
 import androidx.wear.compose.material3.DatePicker
@@ -40,6 +41,7 @@
 import androidx.wear.compose.material3.samples.DatePickerYearMonthDaySample
 import java.time.LocalDate
 import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
 
 @RequiresApi(Build.VERSION_CODES.O)
 val DatePickerDemos =
@@ -49,6 +51,7 @@
         ComposableDemo("Date Day-Month-Year") { DatePickerDemo(DatePickerType.DayMonthYear) },
         ComposableDemo("Date System date format") { DatePickerSample() },
         ComposableDemo("Date Range") { DatePickerMinDateMaxDateSample() },
+        ComposableDemo("Past only") { DatePickerPastOnlyDemo() },
     )
 
 @RequiresApi(Build.VERSION_CODES.O)
@@ -85,3 +88,37 @@
         }
     }
 }
+
+@RequiresApi(Build.VERSION_CODES.O)
+@Composable
+fun DatePickerPastOnlyDemo() {
+    val currentDate = LocalDate.now()
+    var showDatePicker by remember { mutableStateOf(true) }
+    var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+    val formatter =
+        DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
+            .withLocale(LocalConfiguration.current.locales[0])
+    if (showDatePicker) {
+        DatePicker(
+            initialDate = datePickerDate, // Initialize with last picked date on reopen
+            onDatePicked = {
+                datePickerDate = it
+                showDatePicker = false
+            },
+            datePickerType = DatePickerType.YearMonthDay,
+            maxDate = currentDate
+        )
+    } else {
+        Box(
+            modifier = Modifier.fillMaxSize(),
+            contentAlignment = Alignment.Center,
+        ) {
+            Button(
+                onClick = { showDatePicker = true },
+                label = { Text("Selected Date") },
+                secondaryLabel = { Text(datePickerDate.format(formatter)) },
+                icon = { Icon(imageVector = Icons.Filled.Edit, contentDescription = "Edit") },
+            )
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PageIndicatorDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PageIndicatorDemo.kt
new file mode 100644
index 0000000..b0ac510
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PageIndicatorDemo.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2024 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.demos
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.wear.compose.foundation.pager.HorizontalPager
+import androidx.wear.compose.foundation.pager.VerticalPager
+import androidx.wear.compose.foundation.pager.rememberPagerState
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.material3.HorizontalPageIndicator
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.VerticalPageIndicator
+import androidx.wear.compose.material3.samples.HorizontalPageIndicatorWithPagerSample
+import androidx.wear.compose.material3.samples.VerticalPageIndicatorWithPagerSample
+
+val PageIndicatorDemos =
+    listOf(
+        ComposableDemo("Horizontal PageIndicator") { HorizontalPageIndicatorWithPagerSample() },
+        ComposableDemo("Vertical PageIndicator") { VerticalPageIndicatorWithPagerSample() },
+        ComposableDemo("Vertical pager on left") { VerticalPageIndicatorWithPagerOnLeftSample() },
+        ComposableDemo("Horizontal with white background") {
+            HorizontalPageIndicatorWhiteBackgroundDemo()
+        },
+    )
+
+@Composable
+fun HorizontalPageIndicatorWhiteBackgroundDemo() {
+    val pageCount = 9
+    val pagerState = rememberPagerState { pageCount }
+
+    Box(modifier = Modifier.background(Color.White)) {
+        HorizontalPager(
+            state = pagerState,
+        ) { page ->
+            Box(modifier = Modifier.fillMaxSize()) {
+                Text(
+                    modifier = Modifier.align(Alignment.Center),
+                    text = "Page #$page",
+                    color = Color.Black
+                )
+            }
+        }
+        HorizontalPageIndicator(pagerState = pagerState)
+    }
+}
+
+@Composable
+fun VerticalPageIndicatorWithPagerOnLeftSample() {
+    val pageCount = 9
+    val pagerState = rememberPagerState { pageCount }
+
+    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+        Box {
+            VerticalPager(
+                state = pagerState,
+            ) { page ->
+                Box(modifier = Modifier.fillMaxSize()) {
+                    Text(modifier = Modifier.align(Alignment.Center), text = "Page #$page")
+                }
+            }
+            VerticalPageIndicator(pagerState = pagerState)
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PlaceholderDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PlaceholderDemo.kt
index bf7184c..79493f9 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PlaceholderDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/PlaceholderDemo.kt
@@ -405,7 +405,7 @@
                     placeholderState = buttonPlaceholderState
                 )
         )
-        if (!buttonPlaceholderState.isShowContent) {
+        if (!buttonPlaceholderState.isHidden) {
             Button(
                 modifier =
                     modifier
@@ -457,7 +457,7 @@
             )
         }
     }
-    LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.startPlaceholderAnimation() }
+    LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.animatePlaceholder() }
 }
 
 @Composable
@@ -532,7 +532,7 @@
                 placeholderState = buttonPlaceholderState
             )
     )
-    LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.startPlaceholderAnimation() }
+    LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.animatePlaceholder() }
 }
 
 @Composable
@@ -553,7 +553,7 @@
         ) {
             if (content != null) content()
         }
-        if (!cardPlaceholderState.isShowContent) {
+        if (!cardPlaceholderState.isHidden) {
             AppCard(
                 onClick = {},
                 appName = {
@@ -596,5 +596,5 @@
             }
         }
     }
-    LaunchedEffect(cardPlaceholderState) { cardPlaceholderState.startPlaceholderAnimation() }
+    LaunchedEffect(cardPlaceholderState) { cardPlaceholderState.animatePlaceholder() }
 }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwipeToRevealDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwipeToRevealDemo.kt
index 4c33f50..e67c9f9 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwipeToRevealDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwipeToRevealDemo.kt
@@ -246,3 +246,29 @@
         }
     }
 }
+
+@Composable
+fun SwipeToRevealSingleButtonWithAnchoring() {
+    SwipeToReveal(
+        revealState =
+            rememberRevealState(
+                swipeDirection = SwipeDirection.RightToLeft,
+                anchorWidth = SwipeToRevealDefaults.SingleActionAnchorWidth,
+            ),
+        actions = {
+            primaryAction(
+                onClick = { /* This block is called when the primary action is executed. */ },
+                icon = { Icon(Icons.Outlined.Delete, contentDescription = "Delete") },
+                label = "Delete"
+            )
+            undoPrimaryAction(
+                onClick = { /* This block is called when the undo primary action is executed. */ },
+                label = "Undo Delete"
+            )
+        }
+    ) {
+        Button(modifier = Modifier.fillMaxWidth(), onClick = {}) {
+            Text("This Button has only one action", modifier = Modifier.fillMaxSize())
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
index 40119b4..108dbdb 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
@@ -30,7 +30,6 @@
 import androidx.wear.compose.material3.samples.EdgeButtonSample
 import androidx.wear.compose.material3.samples.EdgeSwipeForSwipeToDismiss
 import androidx.wear.compose.material3.samples.FixedFontSize
-import androidx.wear.compose.material3.samples.HorizontalPageIndicatorWithPagerSample
 import androidx.wear.compose.material3.samples.HorizontalPagerScaffoldSample
 import androidx.wear.compose.material3.samples.ScaffoldSample
 import androidx.wear.compose.material3.samples.SimpleSwipeToDismissBox
@@ -40,7 +39,6 @@
 import androidx.wear.compose.material3.samples.SwipeToRevealSingleActionCardSample
 import androidx.wear.compose.material3.samples.TransformingLazyColumnScalingMorphingEffectSample
 import androidx.wear.compose.material3.samples.TransformingLazyColumnTargetMorphingHeightSample
-import androidx.wear.compose.material3.samples.VerticalPageIndicatorWithPagerSample
 import androidx.wear.compose.material3.samples.VerticalPagerScaffoldSample
 
 val WearMaterial3Demos =
@@ -148,20 +146,13 @@
                         },
                     )
                 ),
-                Material3DemoCategory(
-                    title = "Page Indicator",
-                    listOf(
-                        ComposableDemo("HorizontalPageIndicator") {
-                            HorizontalPageIndicatorWithPagerSample()
-                        },
-                        ComposableDemo("VerticalPageIndicator") {
-                            VerticalPageIndicatorWithPagerSample()
-                        },
-                    )
-                ),
+                Material3DemoCategory(title = "Page Indicator", PageIndicatorDemos),
                 Material3DemoCategory(
                     title = "Swipe to Reveal",
                     listOf(
+                        ComposableDemo("Single Action with Anchoring") {
+                            Centralize { SwipeToRevealSingleButtonWithAnchoring() }
+                        },
                         ComposableDemo("Bi-directional / Non-anchoring") {
                             Centralize { SwipeToRevealBothDirectionsNonAnchoring() }
                         },
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/MacrobenchmarkScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/MacrobenchmarkScreen.kt
new file mode 100644
index 0000000..67330d5
--- /dev/null
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/MacrobenchmarkScreen.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 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.macrobenchmark.common
+
+import androidx.benchmark.macro.MacrobenchmarkScope
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.runtime.Composable
+
+/** Represents a screen that can be used in Macrobenchmark tests. */
+interface MacrobenchmarkScreen {
+    val content: @Composable BoxScope.() -> Unit
+    val exercise: MacrobenchmarkScope.() -> Unit
+        get() = { device.waitForIdle() }
+}
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TransformingLazyColumnBenchmark.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TransformingLazyColumnBenchmark.kt
new file mode 100644
index 0000000..ccf678d
--- /dev/null
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TransformingLazyColumnBenchmark.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2024 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.macrobenchmark.common
+
+import android.graphics.Point
+import androidx.benchmark.macro.MacrobenchmarkScope
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.dp
+import androidx.test.uiautomator.By
+import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
+import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
+import androidx.wear.compose.material3.AppScaffold
+import androidx.wear.compose.material3.EdgeButton
+import androidx.wear.compose.material3.EdgeButtonSize
+import androidx.wear.compose.material3.MaterialTheme
+import androidx.wear.compose.material3.ScreenScaffold
+import androidx.wear.compose.material3.ScreenScaffoldDefaults
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.lazy.scrollTransform
+import kotlinx.coroutines.launch
+
+val TransformingLazyColumnBenchmark =
+    object : MacrobenchmarkScreen {
+        override val content: @Composable (BoxScope.() -> Unit)
+            get() = {
+                val state = rememberTransformingLazyColumnState()
+                val coroutineScope = rememberCoroutineScope()
+                AppScaffold {
+                    ScreenScaffold(
+                        state,
+                        edgeButton = {
+                            EdgeButton(
+                                onClick = { coroutineScope.launch { state.scrollToItem(1) } }
+                            ) {
+                                Text("To top")
+                            }
+                        }
+                    ) {
+                        TransformingLazyColumn(
+                            state = state,
+                            contentPadding =
+                                ScreenScaffoldDefaults.contentPaddingWithEdgeButton(
+                                    EdgeButtonSize.Small,
+                                    start = 10.dp,
+                                    end = 10.dp,
+                                    top = 20.dp,
+                                    extraBottom = 20.dp
+                                ),
+                            modifier =
+                                Modifier.background(MaterialTheme.colorScheme.background)
+                                    .semantics { contentDescription = CONTENT_DESCRIPTION }
+                        ) {
+                            items(5000) {
+                                Text(
+                                    "Item $it",
+                                    color = MaterialTheme.colorScheme.onSurface,
+                                    style = MaterialTheme.typography.bodyLarge,
+                                    modifier =
+                                        Modifier.fillMaxWidth()
+                                            // Apply Material 3 Motion transformations.
+                                            .scrollTransform(
+                                                this,
+                                                backgroundColor =
+                                                    MaterialTheme.colorScheme.surfaceContainer,
+                                                shape = MaterialTheme.shapes.small
+                                            )
+                                            .padding(10.dp)
+                                )
+                            }
+                        }
+                    }
+                }
+            }
+
+        override val exercise: MacrobenchmarkScope.() -> Unit
+            get() = {
+                val list = device.findObject(By.desc(CONTENT_DESCRIPTION))
+                // Setting a gesture margin is important otherwise gesture nav is triggered.
+                list.setGestureMargin(device.displayWidth / 5)
+                repeat(5) {
+                    list.drag(Point(list.visibleCenter.x, list.visibleCenter.y / 3))
+                    device.waitForIdle()
+                }
+            }
+    }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/Utils.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/Utils.kt
index 1f54bb2..3cf03ed 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/Utils.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/Utils.kt
@@ -18,7 +18,9 @@
 
 import androidx.test.uiautomator.UiDevice
 
-internal fun numberedContentDescription(n: Int) = "find-me-$n"
+internal val CONTENT_DESCRIPTION = "find-me"
+
+internal fun numberedContentDescription(n: Int) = "$CONTENT_DESCRIPTION-$n"
 
 internal fun UiDevice.scrollDown() {
     swipe(
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AlertDialogScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AlertDialogScreen.kt
index 2b5adb3..762b883 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AlertDialogScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AlertDialogScreen.kt
@@ -46,10 +46,11 @@
 import androidx.wear.compose.material3.MaterialTheme
 import androidx.wear.compose.material3.Text
 import androidx.wear.compose.material3.macrobenchmark.common.FIND_OBJECT_TIMEOUT_MS
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.R
 
 val AlertDialogScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
 
         override val content: @Composable BoxScope.() -> Unit
             get() = {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AnimatedTextScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AnimatedTextScreen.kt
index 6be0bfe..615f51c 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AnimatedTextScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/AnimatedTextScreen.kt
@@ -49,12 +49,13 @@
 import androidx.wear.compose.material3.AnimatedText
 import androidx.wear.compose.material3.Text
 import androidx.wear.compose.material3.macrobenchmark.common.FIND_OBJECT_TIMEOUT_MS
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.R
 import androidx.wear.compose.material3.rememberAnimatedTextFontRegistry
 import kotlinx.coroutines.launch
 
 val AnimatedTextScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/BaselineProfileScreens.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/BaselineProfileScreens.kt
index c50d169..e5b993a 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/BaselineProfileScreens.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/BaselineProfileScreens.kt
@@ -16,10 +16,6 @@
 
 package androidx.wear.compose.material3.macrobenchmark.common.baselineprofile
 
-import androidx.benchmark.macro.MacrobenchmarkScope
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.runtime.Composable
-
 val BaselineProfileScreens =
     listOf(
         AlertDialogScreen,
@@ -56,10 +52,3 @@
         TimePickerScreen,
         TransformingLazyColumnScreen,
     )
-
-/** Represents a screen used for generating a baseline profile. */
-interface BaselineProfileScreen {
-    val content: @Composable BoxScope.() -> Unit
-    val exercise: MacrobenchmarkScope.() -> Unit
-        get() = { device.waitForIdle() }
-}
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonGroupScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonGroupScreen.kt
index 2125418..d7fc697 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonGroupScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonGroupScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.ButtonGroupSample
 
 val ButtonGroupScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { ButtonGroupSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonScreen.kt
index 6274bc5..8766fc3 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ButtonScreen.kt
@@ -25,6 +25,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.painterResource
 import androidx.wear.compose.material3.IconButtonDefaults
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.R
 import androidx.wear.compose.material3.macrobenchmark.common.scrollDown
 import androidx.wear.compose.material3.samples.ButtonSample
@@ -38,7 +39,7 @@
 import androidx.wear.compose.material3.samples.OutlinedCompactButtonSample
 
 val ButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CardScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CardScreen.kt
index 4e149a6..7fbf379 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CardScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CardScreen.kt
@@ -37,11 +37,12 @@
 import androidx.wear.compose.material3.OutlinedCard
 import androidx.wear.compose.material3.Text
 import androidx.wear.compose.material3.TitleCard
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.R
 import androidx.wear.compose.material3.macrobenchmark.common.scrollDown
 
 val CardScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CheckboxButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CheckboxButtonScreen.kt
index 8d8000a..69bf7b3 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CheckboxButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CheckboxButtonScreen.kt
@@ -22,11 +22,12 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.CheckboxButtonSample
 import androidx.wear.compose.material3.samples.SplitCheckboxButtonSample
 
 val CheckboxButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ColorSchemeScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ColorSchemeScreen.kt
index f978ad6..a85413c 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ColorSchemeScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ColorSchemeScreen.kt
@@ -30,10 +30,11 @@
 import androidx.wear.compose.material3.ButtonDefaults
 import androidx.wear.compose.material3.MaterialTheme
 import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.scrollDown
 
 val ColorSchemeScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ConfirmationScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ConfirmationScreen.kt
index 8796147..406042b 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ConfirmationScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ConfirmationScreen.kt
@@ -26,10 +26,8 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.painterResource
@@ -45,11 +43,12 @@
 import androidx.wear.compose.material3.SuccessConfirmation
 import androidx.wear.compose.material3.Text
 import androidx.wear.compose.material3.macrobenchmark.common.FIND_OBJECT_TIMEOUT_MS
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.R
 import androidx.wear.compose.material3.macrobenchmark.common.numberedContentDescription
 
 val ConfirmationScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CurvedTextScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CurvedTextScreen.kt
index e5f6508..f149ecb 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CurvedTextScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/CurvedTextScreen.kt
@@ -18,11 +18,12 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.CurvedTextBottom
 import androidx.wear.compose.material3.samples.CurvedTextTop
 
 val CurvedTextScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 CurvedTextTop()
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt
index 97b1296..a42a4a9 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt
@@ -21,10 +21,11 @@
 import androidx.compose.runtime.Composable
 import androidx.wear.compose.material3.DatePicker
 import androidx.wear.compose.material3.DatePickerType
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import java.time.LocalDate
 
 val DatePickerScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 if (Build.VERSION.SDK_INT >= 26) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/EdgeButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/EdgeButtonScreen.kt
index 910bac1..c2dc7ad 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/EdgeButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/EdgeButtonScreen.kt
@@ -19,11 +19,12 @@
 import androidx.benchmark.macro.MacrobenchmarkScope
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.scrollDown
 import androidx.wear.compose.material3.samples.EdgeButtonSample
 
 val EdgeButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { EdgeButtonSample() }
 
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconButtonScreen.kt
index 31d35a2..799e267 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconButtonScreen.kt
@@ -24,6 +24,7 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.FilledIconButtonSample
 import androidx.wear.compose.material3.samples.FilledTonalIconButtonSample
 import androidx.wear.compose.material3.samples.FilledVariantIconButtonSample
@@ -34,7 +35,7 @@
 
 @OptIn(ExperimentalLayoutApi::class)
 val IconButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable() (BoxScope.() -> Unit)
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconToggleButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconToggleButtonScreen.kt
index 2a170f3..d1b2bb1 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconToggleButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/IconToggleButtonScreen.kt
@@ -36,13 +36,14 @@
 import androidx.wear.compose.material3.IconToggleButton
 import androidx.wear.compose.material3.IconToggleButtonDefaults
 import androidx.wear.compose.material3.macrobenchmark.common.FIND_OBJECT_TIMEOUT_MS
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.R
 import androidx.wear.compose.material3.samples.IconToggleButtonSample
 import androidx.wear.compose.material3.samples.IconToggleButtonVariantSample
 
 @OptIn(ExperimentalLayoutApi::class)
 val IconToggleButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable (BoxScope.() -> Unit)
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ListHeaderScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ListHeaderScreen.kt
index 0cede8a..21a41e5 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ListHeaderScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ListHeaderScreen.kt
@@ -22,12 +22,13 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.ListHeaderSample
 import androidx.wear.compose.material3.samples.ListSubHeaderSample
 import androidx.wear.compose.material3.samples.ListSubHeaderWithIconSample
 
 val ListHeaderScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/OpenOnPhoneDialogScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/OpenOnPhoneDialogScreen.kt
index 1515b55..de4901b 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/OpenOnPhoneDialogScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/OpenOnPhoneDialogScreen.kt
@@ -35,9 +35,10 @@
 import androidx.wear.compose.material3.FilledTonalButton
 import androidx.wear.compose.material3.OpenOnPhoneDialog
 import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 
 val OpenOnPhoneDialogScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PageIndicatorScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PageIndicatorScreen.kt
index 1c069dc..c7c67f4 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PageIndicatorScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PageIndicatorScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.VerticalPageIndicatorWithPagerSample
 
 val PageIndicatorScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { VerticalPageIndicatorWithPagerSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerGroupScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerGroupScreen.kt
index 037263f..4a31a18 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerGroupScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerGroupScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.AutoCenteringPickerGroup
 
 val PickerGroupScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable (BoxScope.() -> Unit)
             get() = { AutoCenteringPickerGroup() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerScreen.kt
index ba68003..3b5c299 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PickerScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.PickerScrollToOption
 
 val PickerScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { PickerScrollToOption() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PlaceHolderScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PlaceHolderScreen.kt
index 1dd1def..5af8a5a 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PlaceHolderScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/PlaceHolderScreen.kt
@@ -22,12 +22,13 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.ButtonWithIconAndLabelAndPlaceholders
 import androidx.wear.compose.material3.samples.ButtonWithIconAndLabelsAndOverlaidPlaceholder
 import androidx.wear.compose.material3.samples.TextPlaceholder
 
 val PlaceHolderScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ProgressIndicatorScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ProgressIndicatorScreen.kt
index 8c3a78b..c9c5b8e 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ProgressIndicatorScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ProgressIndicatorScreen.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.FullScreenProgressIndicatorSample
 import androidx.wear.compose.material3.samples.IndeterminateProgressIndicatorSample
 import androidx.wear.compose.material3.samples.MediaButtonProgressIndicatorSample
@@ -28,7 +29,7 @@
 import androidx.wear.compose.material3.samples.SmallValuesProgressIndicatorSample
 
 val ProgressIndicatorScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 FullScreenProgressIndicatorSample()
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/RadioButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/RadioButtonScreen.kt
index db6b300..bff77db 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/RadioButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/RadioButtonScreen.kt
@@ -22,11 +22,12 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.RadioButtonSample
 import androidx.wear.compose.material3.samples.SplitRadioButtonSample
 
 val RadioButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScaffoldScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScaffoldScreen.kt
index 8a63b05..462a87f 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScaffoldScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScaffoldScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.ScaffoldSample
 
 val ScaffoldScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
 
         override val content: @Composable BoxScope.() -> Unit
             get() = { ScaffoldSample() }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScrollIndicatorScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScrollIndicatorScreen.kt
index 3929d0e..088a27d 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScrollIndicatorScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/ScrollIndicatorScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.ScrollIndicatorWithColumnSample
 
 val ScrollIndicatorScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { ScrollIndicatorWithColumnSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SliderScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SliderScreen.kt
index 5d133de..c622a31 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SliderScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SliderScreen.kt
@@ -23,6 +23,7 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.macrobenchmark.common.scrollDown
 import androidx.wear.compose.material3.samples.ChangedSliderSample
 import androidx.wear.compose.material3.samples.SliderSample
@@ -30,7 +31,7 @@
 import androidx.wear.compose.material3.samples.SliderWithIntegerSample
 
 val SliderScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/StepperScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/StepperScreen.kt
index b262e91..6c89908 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/StepperScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/StepperScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.StepperWithButtonSample
 
 val StepperScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { StepperWithButtonSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToDismissScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToDismissScreen.kt
index 80fe730..482604e 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToDismissScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToDismissScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.StatefulSwipeToDismissBox
 
 val SwipeToDismissScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { StatefulSwipeToDismissBox() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToRevealScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToRevealScreen.kt
index 7356bc9..a940608 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToRevealScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwipeToRevealScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.SwipeToRevealSample
 
 val SwipeToRevealScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { SwipeToRevealSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwitchButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwitchButtonScreen.kt
index e9e98188..2e70194 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwitchButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/SwitchButtonScreen.kt
@@ -22,11 +22,12 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.SplitSwitchButtonSample
 import androidx.wear.compose.material3.samples.SwitchButtonSample
 
 val SwitchButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextButtonScreen.kt
index b9b82e7..e1d202e 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextButtonScreen.kt
@@ -24,6 +24,7 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.FilledTextButtonSample
 import androidx.wear.compose.material3.samples.FilledTonalTextButtonSample
 import androidx.wear.compose.material3.samples.FilledVariantTextButtonSample
@@ -34,7 +35,7 @@
 
 @OptIn(ExperimentalLayoutApi::class)
 val TextButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable (BoxScope.() -> Unit)
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextToggleButtonScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextToggleButtonScreen.kt
index 72a2aa4..833143d 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextToggleButtonScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TextToggleButtonScreen.kt
@@ -35,12 +35,13 @@
 import androidx.wear.compose.material3.TextToggleButton
 import androidx.wear.compose.material3.TextToggleButtonDefaults
 import androidx.wear.compose.material3.macrobenchmark.common.FIND_OBJECT_TIMEOUT_MS
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.LargeTextToggleButtonSample
 import androidx.wear.compose.material3.samples.TextToggleButtonSample
 
 @OptIn(ExperimentalLayoutApi::class)
 val TextToggleButtonScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable (BoxScope.() -> Unit)
             get() = {
                 Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimePickerScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimePickerScreen.kt
index 8022686..f506e50 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimePickerScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimePickerScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.TimePickerSample
 
 val TimePickerScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { TimePickerSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimeTextScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimeTextScreen.kt
index e2b5bb9..5565366 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimeTextScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TimeTextScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.TimeTextWithStatus
 
 val TimeTextScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { TimeTextWithStatus() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TransformingLazyColumnScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TransformingLazyColumnScreen.kt
index ffb08e1..71ba2d3 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TransformingLazyColumnScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/TransformingLazyColumnScreen.kt
@@ -18,10 +18,11 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
+import androidx.wear.compose.material3.macrobenchmark.common.MacrobenchmarkScreen
 import androidx.wear.compose.material3.samples.TransformingLazyColumnScalingMorphingEffectSample
 
 val TransformingLazyColumnScreen =
-    object : BaselineProfileScreen {
+    object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = { TransformingLazyColumnScalingMorphingEffectSample() }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml b/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml
index 40010e2..9e2ee38 100644
--- a/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml
+++ b/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml
@@ -43,6 +43,17 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+
+        <activity
+            android:name=".TransformingLazyColumnActivity"
+            android:theme="@style/AppTheme"
+            android:exported="true">
+            <intent-filter>
+                <action android:name=
+                    "androidx.wear.compose.material3.macrobenchmark.target.TRANSFORMING_LAZY_COLUMN_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
     </application>
 
     <uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TransformingLazyColumnActivity.kt b/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TransformingLazyColumnActivity.kt
new file mode 100644
index 0000000..7bdd7eb
--- /dev/null
+++ b/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TransformingLazyColumnActivity.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 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.macrobenchmark.target
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.MaterialTheme
+import androidx.wear.compose.material3.macrobenchmark.common.TransformingLazyColumnBenchmark
+
+class TransformingLazyColumnActivity : ComponentActivity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContent {
+            MaterialTheme {
+                Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                    TransformingLazyColumnBenchmark.content.invoke(this)
+                }
+            }
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/BaselineProfile.kt b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/BaselineProfile.kt
index 168f053..254e765 100644
--- a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/BaselineProfile.kt
+++ b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/BaselineProfile.kt
@@ -78,7 +78,6 @@
     }
 
     companion object {
-        private const val PACKAGE_NAME = "androidx.wear.compose.material3.macrobenchmark.target"
         private const val BASELINE_ACTIVITY = "$PACKAGE_NAME.BASELINE_ACTIVITY"
     }
 }
diff --git a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/Common.kt b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/Common.kt
new file mode 100644
index 0000000..0a9b71d
--- /dev/null
+++ b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/Common.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2024 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.macrobenchmark
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+
+internal fun disableChargingExperience() {
+    val instrumentation = InstrumentationRegistry.getInstrumentation()
+    val device = UiDevice.getInstance(instrumentation)
+    device.executeShellCommand(
+        "am broadcast -a " +
+            "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
+            "--ez value \"false\" com.google.android.wearable.sysui"
+    )
+}
+
+internal fun enableChargingExperience() {
+    val instrumentation = InstrumentationRegistry.getInstrumentation()
+    val device = UiDevice.getInstance(instrumentation)
+    device.executeShellCommand(
+        "am broadcast -a " +
+            "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
+            "--ez value \"true\" com.google.android.wearable.sysui"
+    )
+}
+
+internal const val PACKAGE_NAME = "androidx.wear.compose.material3.macrobenchmark.target"
diff --git a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TransformingLazyColumnBenchmark.kt b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TransformingLazyColumnBenchmark.kt
new file mode 100644
index 0000000..1f82ab3
--- /dev/null
+++ b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TransformingLazyColumnBenchmark.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2024 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.macrobenchmark
+
+import android.content.Intent
+import androidx.benchmark.macro.CompilationMode
+import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.junit4.MacrobenchmarkRule
+import androidx.test.filters.LargeTest
+import androidx.testutils.createCompilationParams
+import androidx.wear.compose.material3.macrobenchmark.common.TransformingLazyColumnBenchmark
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+class TransformingLazyColumnBenchmark(private val compilationMode: CompilationMode) {
+    @get:Rule val benchmarkRule = MacrobenchmarkRule()
+
+    @Before
+    fun setUp() {
+        disableChargingExperience()
+    }
+
+    @After
+    fun destroy() {
+        enableChargingExperience()
+    }
+
+    @Test
+    fun start() {
+        benchmarkRule.measureRepeated(
+            packageName = PACKAGE_NAME,
+            metrics = listOf(FrameTimingMetric()),
+            compilationMode = compilationMode,
+            iterations = 10,
+            setupBlock = {
+                val intent = Intent()
+                intent.action = TRANSFORMING_LAZY_COLUMN_ACTIVITY
+                startActivityAndWait(intent)
+            }
+        ) {
+            TransformingLazyColumnBenchmark.exercise.invoke(this)
+        }
+    }
+
+    companion object {
+
+        private const val TRANSFORMING_LAZY_COLUMN_ACTIVITY =
+            "$PACKAGE_NAME.TRANSFORMING_LAZY_COLUMN_ACTIVITY"
+
+        @Parameterized.Parameters(name = "compilation={0}")
+        @JvmStatic
+        fun parameters() = createCompilationParams()
+    }
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PageIndicatorSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PageIndicatorSample.kt
index 7ac6bd4..306f628 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PageIndicatorSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PageIndicatorSample.kt
@@ -22,7 +22,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
 import androidx.wear.compose.foundation.pager.HorizontalPager
 import androidx.wear.compose.foundation.pager.VerticalPager
 import androidx.wear.compose.foundation.pager.rememberPagerState
@@ -32,7 +31,6 @@
 
 @Sampled
 @Composable
-@OptIn(ExperimentalWearFoundationApi::class)
 fun HorizontalPageIndicatorWithPagerSample() {
     val pageCount = 9
     val pagerState = rememberPagerState { pageCount }
@@ -51,7 +49,6 @@
 
 @Sampled
 @Composable
-@OptIn(ExperimentalWearFoundationApi::class)
 fun VerticalPageIndicatorWithPagerSample() {
     val pageCount = 9
     val pagerState = rememberPagerState { pageCount }
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PlaceholderSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PlaceholderSample.kt
index fedc367..50aa05f 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PlaceholderSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PlaceholderSample.kt
@@ -106,10 +106,8 @@
         delay(1000)
         labelText = "A label"
     }
-    if (!buttonPlaceholderState.isShowContent) {
-        LaunchedEffect(buttonPlaceholderState) {
-            buttonPlaceholderState.startPlaceholderAnimation()
-        }
+    if (!buttonPlaceholderState.isHidden) {
+        LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.animatePlaceholder() }
     }
 }
 
@@ -135,7 +133,7 @@
         labelText.isNotEmpty() && secondaryLabelText.isNotEmpty() && imageVector != null
     }
     Box {
-        if (buttonPlaceholderState.isShowContent || buttonPlaceholderState.isWipeOff) {
+        if (buttonPlaceholderState.isHidden || buttonPlaceholderState.isWipingOff) {
             Button(
                 onClick = { /* Do something */ },
                 enabled = true,
@@ -171,7 +169,7 @@
                 modifier = Modifier.fillMaxWidth()
             )
         }
-        if (!buttonPlaceholderState.isShowContent) {
+        if (!buttonPlaceholderState.isHidden) {
             Button(
                 onClick = { /* Do something */ },
                 enabled = true,
@@ -220,10 +218,8 @@
         delay(500)
         labelText = "A label"
     }
-    if (!buttonPlaceholderState.isShowContent) {
-        LaunchedEffect(buttonPlaceholderState) {
-            buttonPlaceholderState.startPlaceholderAnimation()
-        }
+    if (!buttonPlaceholderState.isHidden) {
+        LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.animatePlaceholder() }
     }
 }
 
@@ -255,9 +251,7 @@
         delay(3000)
         labelText = "A label"
     }
-    if (!buttonPlaceholderState.isShowContent) {
-        LaunchedEffect(buttonPlaceholderState) {
-            buttonPlaceholderState.startPlaceholderAnimation()
-        }
+    if (!buttonPlaceholderState.isHidden) {
+        LaunchedEffect(buttonPlaceholderState) { buttonPlaceholderState.animatePlaceholder() }
     }
 }
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
index 5e3ffa6..e13753d 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
@@ -317,6 +317,7 @@
             baseShape,
             pressedShape,
             0.75f,
+            8,
             color = { IconButtonDefaults.filledIconButtonColors().containerColor }
         ) { modifier ->
             FilledIconButton(
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt
index 6c5c90e..cee8cc6 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt
@@ -23,10 +23,13 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.testutils.assertContainsColor
 import androidx.compose.testutils.assertShape
 import androidx.compose.ui.Modifier
@@ -621,6 +624,90 @@
     }
 
     @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun animates_corners_to_75_percent_on_click() {
+        val uncheckedShape = RoundedCornerShape(20.dp)
+        val checkedShape = RoundedCornerShape(10.dp)
+        val pressedShape = RoundedCornerShape(0.dp)
+        // Ignore the color transition from unchecked to checked color
+        val colors =
+            IconToggleButtonColors(
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black
+            )
+
+        rule.verifyRoundedButtonTapAnimationEnd(
+            uncheckedShape,
+            pressedShape,
+            0.75f,
+            8,
+            color = { colors.checkedContainerColor }
+        ) { modifier ->
+            IconToggleButton(
+                checked = false,
+                onCheckedChange = {},
+                modifier = modifier,
+                shapes = IconToggleButtonShapes(uncheckedShape, checkedShape, pressedShape),
+                colors = colors
+            ) {}
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun changes_unchecked_to_checked_shape_on_click() {
+        val uncheckedShape = RoundedCornerShape(20.dp)
+        val checkedShape = RoundedCornerShape(10.dp)
+        val pressedShape = RoundedCornerShape(0.dp)
+        rule.verifyRoundedButtonTapAnimationEnd(
+            uncheckedShape,
+            checkedShape,
+            1f,
+            100,
+            color = { IconToggleButtonDefaults.iconToggleButtonColors().checkedContainerColor },
+            antiAliasingGap = 4f,
+        ) { modifier ->
+            var checked by remember { mutableStateOf(false) }
+            IconToggleButton(
+                checked = checked,
+                onCheckedChange = { checked = !checked },
+                modifier = modifier,
+                shapes = IconToggleButtonShapes(uncheckedShape, checkedShape, pressedShape)
+            ) {}
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun changes_checked_to_unchecked_shape_on_click() {
+        val uncheckedShape = RoundedCornerShape(10.dp)
+        val checkedShape = RoundedCornerShape(20.dp)
+        val pressedShape = RoundedCornerShape(0.dp)
+        rule.verifyRoundedButtonTapAnimationEnd(
+            checkedShape,
+            uncheckedShape,
+            1f,
+            100,
+            color = { IconToggleButtonDefaults.iconToggleButtonColors().uncheckedContainerColor },
+            antiAliasingGap = 4f,
+        ) { modifier ->
+            var checked by remember { mutableStateOf(true) }
+            IconToggleButton(
+                checked = checked,
+                onCheckedChange = { checked = !checked },
+                modifier = modifier,
+                shapes = IconToggleButtonShapes(uncheckedShape, checkedShape, pressedShape)
+            ) {}
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyIconToggleButtonColors(
         status: Status,
         checked: Boolean,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
index f383b29..adb74f9 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
@@ -403,7 +403,9 @@
     baseShape: RoundedCornerShape,
     pressedShape: RoundedCornerShape,
     targetProgress: Float,
+    expectedFramesUntilTarget: Int,
     color: @Composable () -> Color,
+    antiAliasingGap: Float = 2f,
     content: @Composable (Modifier) -> Unit
 ) {
     val expectedAnimationEnd =
@@ -426,7 +428,7 @@
      * 2) rule.mainClock.waitUntil expects a condition. However, the shape validations for
      *    ImageBitMap only includes of assets
      */
-    repeat(8) { mainClock.advanceTimeByFrame() }
+    repeat(expectedFramesUntilTarget) { mainClock.advanceTimeByFrame() }
 
     onNodeWithTag(TEST_TAG)
         .captureToImage()
@@ -436,7 +438,7 @@
             verticalPadding = 0.dp,
             shapeColor = fillColor,
             backgroundColor = Color.Transparent,
-            antiAliasingGap = 2.0f,
+            antiAliasingGap = antiAliasingGap,
             shape = expectedAnimationEnd,
         )
 }
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt
index 9383e90..3234616 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt
@@ -57,12 +57,12 @@
         }
 
         // For testing we need to manually manage the frame clock for the placeholder animation
-        placeholderState.initializeTestFrameMillis(PlaceholderStage.ShowContent)
+        placeholderState.initializeTestFrameMillis(PlaceholderStage.HidePlaceholder)
 
         // Advance placeholder clock without changing the content ready and confirm still in
         // ShowPlaceholder
         placeholderState.advanceToNextPlaceholderAnimationLoopAndCheckStage(
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
     }
 
@@ -92,7 +92,7 @@
         // Advance the clock by one cycle and check we have moved to ShowContent
         placeholderState.advanceFrameMillisAndCheckState(
             PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
     }
 
@@ -112,12 +112,12 @@
         }
 
         // For testing we need to manually manage the frame clock for the placeholder animation
-        placeholderState.initializeTestFrameMillis(PlaceholderStage.ShowContent)
+        placeholderState.initializeTestFrameMillis(PlaceholderStage.HidePlaceholder)
 
         // Advance placeholder clock without changing the content ready and confirm still in
         // ShowPlaceholder
         placeholderState.advanceToNextPlaceholderAnimationLoopAndCheckStage(
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
 
         contentReady.value = false
@@ -182,7 +182,7 @@
         // Advance the clock by one cycle and check we have moved to ShowContent
         placeholderState.advanceFrameMillisAndCheckState(
             PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
 
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedBackgroundColor)
@@ -240,7 +240,7 @@
         // Advance the clock by one cycle and check we have moved to ShowContent
         placeholderState.advanceFrameMillisAndCheckState(
             PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
 
         // Check that the shimmer is no longer visible
@@ -317,7 +317,7 @@
         // Now move the end of the wipe-off and confirm that the proper button background is visible
         placeholderState.advanceFrameMillisAndCheckState(
             PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
 
         // Check that normal button background is now visible
@@ -338,7 +338,7 @@
                     placeholderState = placeholderState,
                 ),
         )
-        LaunchedEffect(placeholderState) { placeholderState.startPlaceholderAnimation() }
+        LaunchedEffect(placeholderState) { placeholderState.animatePlaceholder() }
     }
 
     @Test
@@ -366,7 +366,7 @@
 
         placeholderState.value?.advanceFrameMillisAndCheckState(
             PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
     }
 
@@ -392,7 +392,7 @@
                         placeholderState = placeholderState,
                     ),
             )
-            LaunchedEffect(placeholderState) { placeholderState.startPlaceholderAnimation() }
+            LaunchedEffect(placeholderState) { placeholderState.animatePlaceholder() }
         }
 
         placeholderState.initializeTestFrameMillis()
@@ -408,7 +408,7 @@
 
         placeholderState.advanceFrameMillisAndCheckState(
             PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
-            PlaceholderStage.ShowContent
+            PlaceholderStage.HidePlaceholder
         )
 
         // Check the placeholder background has gone and that we can see the buttons background
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
index 202c8b9..3a64620 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
@@ -536,6 +536,7 @@
             baseShape,
             pressedShape,
             0.75f,
+            8,
             color = { TextButtonDefaults.filledTextButtonColors().containerColor }
         ) { modifier ->
             TextButton(
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt
index 1455f333..2b3d35e 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt
@@ -23,10 +23,13 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.testutils.assertContainsColor
 import androidx.compose.testutils.assertShape
 import androidx.compose.ui.Modifier
@@ -604,6 +607,90 @@
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
     }
 
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun animates_corners_to_75_percent_on_click() {
+        val uncheckedShape = RoundedCornerShape(20.dp)
+        val checkedShape = RoundedCornerShape(10.dp)
+        val pressedShape = RoundedCornerShape(0.dp)
+        // Ignore the color transition from unchecked to checked color
+        val colors =
+            TextToggleButtonColors(
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black,
+                Color.Black
+            )
+
+        rule.verifyRoundedButtonTapAnimationEnd(
+            uncheckedShape,
+            pressedShape,
+            0.75f,
+            8,
+            color = { colors.checkedContainerColor }
+        ) { modifier ->
+            TextToggleButton(
+                checked = false,
+                onCheckedChange = {},
+                modifier = modifier,
+                shapes = TextToggleButtonShapes(uncheckedShape, checkedShape, pressedShape),
+                colors = colors
+            ) {}
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun changes_unchecked_to_checked_shape_on_click() {
+        val uncheckedShape = RoundedCornerShape(20.dp)
+        val checkedShape = RoundedCornerShape(10.dp)
+        val pressedShape = RoundedCornerShape(0.dp)
+        rule.verifyRoundedButtonTapAnimationEnd(
+            uncheckedShape,
+            checkedShape,
+            1f,
+            100,
+            color = { TextToggleButtonDefaults.textToggleButtonColors().checkedContainerColor },
+            antiAliasingGap = 4f,
+        ) { modifier ->
+            var checked by remember { mutableStateOf(false) }
+            TextToggleButton(
+                checked = checked,
+                onCheckedChange = { checked = !checked },
+                modifier = modifier,
+                shapes = TextToggleButtonShapes(uncheckedShape, checkedShape, pressedShape)
+            ) {}
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun changes_checked_to_unchecked_shape_on_click() {
+        val uncheckedShape = RoundedCornerShape(10.dp)
+        val checkedShape = RoundedCornerShape(20.dp)
+        val pressedShape = RoundedCornerShape(0.dp)
+        rule.verifyRoundedButtonTapAnimationEnd(
+            checkedShape,
+            uncheckedShape,
+            1f,
+            100,
+            color = { TextToggleButtonDefaults.textToggleButtonColors().uncheckedContainerColor },
+            antiAliasingGap = 4f,
+        ) { modifier ->
+            var checked by remember { mutableStateOf(true) }
+            TextToggleButton(
+                checked = checked,
+                onCheckedChange = { checked = !checked },
+                modifier = modifier,
+                shapes = TextToggleButtonShapes(uncheckedShape, checkedShape, pressedShape)
+            ) {}
+        }
+    }
+
     @Composable
     private fun shapeColor(): Color {
         return TextToggleButtonDefaults.textToggleButtonColors()
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedToggleRoundedCornerShape.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedToggleRoundedCornerShape.kt
index f660f8f..a4a8ebc 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedToggleRoundedCornerShape.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedToggleRoundedCornerShape.kt
@@ -16,49 +16,53 @@
 
 package androidx.wear.compose.material3
 
+import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.FiniteAnimationSpec
-import androidx.compose.animation.core.animateFloat
-import androidx.compose.animation.core.updateTransition
 import androidx.compose.foundation.shape.CornerSize
-import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.geometry.RoundRect
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.geometry.toRect
 import androidx.compose.ui.graphics.Outline
 import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.LayoutDirection
+import kotlinx.coroutines.launch
 
 /**
- * A animated [RoundedCornerShape]. Animation is driven by changes to the [cornerSize] lambda.
- * [currentShapeSize] is provided as Size is received here, but must affect the animation.
+ * An implementation similar to RoundedCornerShape, but based on linear interpolation between a
+ * start and stop CornerSize, and an observable progress between 0.0 and 1.0.
  *
- * @param currentShapeSize MutableState coordinating the current size.
- * @param cornerSize a lambda resolving to the current Corner size.
+ * @param startCornerSize the corner size when progress is 0.0
+ * @param endCornerSize the corner size when progress is 1.0
+ * @param progress returns the current progress from start to stop.
  */
 @Stable
-internal class AnimatedToggleRoundedCornerShape(
-    private val currentShapeSize: MutableState<Size?>,
-    private val cornerSize: () -> CornerSize,
+private class AnimatedToggleRoundedCornerShape(
+    var startCornerSize: CornerSize,
+    var endCornerSize: CornerSize,
+    var progress: () -> Float,
 ) : Shape {
     override fun createOutline(
         size: Size,
         layoutDirection: LayoutDirection,
         density: Density,
     ): Outline {
-        val cornerRadius = cornerSize().toPx(size, density)
-
-        currentShapeSize.value = size
+        val animatedCornerSize = AnimatedCornerSize(startCornerSize, endCornerSize, progress)
+        val animatedCornerSizePx = animatedCornerSize.toPx(size, density)
 
         return Outline.Rounded(
             roundRect =
-                RoundRect(rect = size.toRect(), radiusX = cornerRadius, radiusY = cornerRadius)
+                RoundRect(
+                    rect = size.toRect(),
+                    radiusX = animatedCornerSizePx,
+                    radiusY = animatedCornerSizePx
+                )
         )
     }
 }
@@ -84,49 +88,41 @@
             else -> ToggleState.Unchecked
         }
 
-    val transition = updateTransition(toggleState, label = "Toggle State")
-    val density = LocalDensity.current
+    val previous = remember { mutableStateOf(toggleState) }
+    val scope = rememberCoroutineScope()
+    val progress = remember { Animatable(1f) }
 
-    val currentShapeSize = remember { mutableStateOf<Size?>(null) }
+    val toggledCornerSize =
+        toggleState.cornerSize(uncheckedCornerSize, checkedCornerSize, pressedCornerSize)
+    val animationSpec = if (pressed) onPressAnimationSpec else onReleaseAnimationSpec
 
-    val observedSize = currentShapeSize.value
+    val animatedShape = remember {
+        AnimatedToggleRoundedCornerShape(
+            startCornerSize = toggledCornerSize,
+            endCornerSize = toggledCornerSize,
+            progress = { progress.value },
+        )
+    }
 
-    if (observedSize != null) {
-        val sizePx =
-            transition.animateFloat(
-                label = "Corner Size",
-                transitionSpec = {
-                    when {
-                        targetState isTransitioningTo ToggleState.Pressed -> onPressAnimationSpec
-                        else -> onReleaseAnimationSpec
-                    }
-                },
-            ) { newState ->
-                newState
-                    .cornerSize(uncheckedCornerSize, checkedCornerSize, pressedCornerSize)
-                    .toPx(observedSize, density)
-            }
-
-        return remember(sizePx) {
-            AnimatedToggleRoundedCornerShape(
-                currentShapeSize = currentShapeSize,
-            ) {
-                CornerSize(sizePx.value)
-            }
+    LaunchedEffect(toggleState) {
+        // Allow the press up animation to finish its minimum duration before starting the next
+        if (!pressed) {
+            waitUntil { !progress.isRunning || progress.value > MIN_REQUIRED_ANIMATION_PROGRESS }
         }
-    } else {
-        return remember(toggleState, uncheckedCornerSize, checkedCornerSize, pressedCornerSize) {
-            AnimatedToggleRoundedCornerShape(
-                currentShapeSize = currentShapeSize,
-            ) {
-                toggleState.cornerSize(
-                    uncheckedCornerSize,
-                    checkedCornerSize,
-                    pressedCornerSize,
-                )
+
+        if (toggleState != previous.value) {
+            animatedShape.startCornerSize = animatedShape.endCornerSize
+            animatedShape.endCornerSize = toggledCornerSize
+            previous.value = toggleState
+
+            scope.launch {
+                progress.snapTo(1f - progress.value)
+                progress.animateTo(1f, animationSpec = animationSpec)
             }
         }
     }
+
+    return animatedShape
 }
 
 private fun ToggleState.cornerSize(
@@ -145,3 +141,5 @@
     Checked,
     Pressed,
 }
+
+private const val MIN_REQUIRED_ANIMATION_PROGRESS = 0.75f
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt
index 11dbdef..f28dd95 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt
@@ -26,6 +26,7 @@
 import androidx.compose.animation.core.SpringSpec
 import androidx.compose.animation.core.TwoWayConverter
 import androidx.compose.animation.core.VectorizedAnimationSpec
+import androidx.compose.runtime.withFrameMillis
 
 /**
  * Returns a new [AnimationSpec] that is a faster version of this one.
@@ -129,3 +130,14 @@
     }
         as T
 }
+
+internal suspend fun waitUntil(condition: () -> Boolean) {
+    val initialTimeMillis = withFrameMillis { it }
+    while (!condition()) {
+        val timeMillis = withFrameMillis { it }
+        if (timeMillis - initialTimeMillis > MAX_WAIT_TIME_MILLIS) return
+    }
+    return
+}
+
+private const val MAX_WAIT_TIME_MILLIS = 1_000L
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt
index 69996bc..86d0df6 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt
@@ -17,8 +17,7 @@
 package androidx.wear.compose.material3
 
 import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.tween
+import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.Interaction
@@ -63,7 +62,6 @@
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import androidx.wear.compose.material3.tokens.CheckboxButtonTokens
-import androidx.wear.compose.material3.tokens.MotionTokens
 import androidx.wear.compose.material3.tokens.ShapeTokens
 import androidx.wear.compose.material3.tokens.SplitCheckboxButtonTokens
 import androidx.wear.compose.materialcore.animateSelectionColor
@@ -1526,7 +1524,7 @@
 private val SPLIT_MIN_WIDTH = 48.dp
 private val SPLIT_SECTIONS_SHAPE = ShapeTokens.CornerExtraSmall
 
-private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
-    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
-private val PROGRESS_ANIMATION_SPEC: TweenSpec<Float> =
-    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
+private val COLOR_ANIMATION_SPEC: AnimationSpec<Color>
+    @Composable get() = MaterialTheme.motionScheme.slowEffectsSpec()
+private val PROGRESS_ANIMATION_SPEC: FiniteAnimationSpec<Float>
+    @Composable get() = MaterialTheme.motionScheme.fastEffectsSpec()
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Placeholder.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Placeholder.kt
index 8eef2be..cca2673 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Placeholder.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Placeholder.kt
@@ -100,7 +100,7 @@
 @Composable
 fun Modifier.placeholder(
     placeholderState: PlaceholderState,
-    shape: Shape = PlaceholderDefaults.shape,
+    shape: Shape = PlaceholderDefaults.Shape,
     color: Color =
         MaterialTheme.colorScheme.onSurface
             .copy(alpha = 0.1f)
@@ -152,7 +152,7 @@
 @Composable
 fun Modifier.placeholderShimmer(
     placeholderState: PlaceholderState,
-    shape: Shape = PlaceholderDefaults.shape,
+    shape: Shape = PlaceholderDefaults.Shape,
     color: Color = MaterialTheme.colorScheme.onSurface,
 ): Modifier =
     this.then(
@@ -175,8 +175,8 @@
     )
 
 /**
- * Creates a [PlaceholderState] that is remembered across compositions. To start placeholder
- * animations run [PlaceholderState.startPlaceholderAnimation].
+ * Creates a [PlaceholderState] that is remembered across compositions. To animate the placeholder
+ * depending on the state, run [PlaceholderState.animatePlaceholder].
  *
  * A [PlaceholderState] should be created for each component that has placeholder data. The state is
  * used to coordinate all of the different placeholder effects and animations.
@@ -222,15 +222,15 @@
 object PlaceholderDefaults {
 
     /** Default [Shape] for Placeholder. */
-    val shape: Shape = ShapeTokens.CornerFull
+    val Shape: Shape = ShapeTokens.CornerFull
 
     /**
      * Create a [ButtonColors] that can be used in placeholder mode. This will provide the
      * placeholder background effect that covers the normal button background with a solid
      * background of [color] when the [placeholderState] is set to show the placeholder and a wipe
      * off gradient brush when the state is in wipe-off mode. If the state is
-     * [PlaceholderState.isShowContent] then the normal background will be used. All other colors
-     * will be delegated to [originalButtonColors].
+     * [PlaceholderState.isHidden] then the normal background will be used. All other colors will be
+     * delegated to [originalButtonColors].
      *
      * Example of a [Button] with icon and a label that put placeholders over individual content
      * slots and then draws a placeholder shimmer over the result and draws over the [Button]s
@@ -248,7 +248,7 @@
         placeholderState: PlaceholderState,
         color: Color = MaterialTheme.colorScheme.surfaceContainer
     ): ButtonColors {
-        return if (!placeholderState.isShowContent) {
+        return if (!placeholderState.isHidden) {
             ButtonColors(
                 containerPainter =
                     PlaceholderBackgroundPainter(
@@ -318,37 +318,37 @@
 
     /**
      * Create a [Painter] that wraps another painter and overlays a placeholder background brush on
-     * top. If the [placeholderState] is [PlaceholderState.isShowContent] the original painter will
-     * be used. Otherwise the [painter] will be drawn and then a placeholder background will be
+     * top. If the [placeholderState] is [PlaceholderState.isHidden] the original painter will be
+     * used. Otherwise the [originalPainter] will be drawn and then a placeholder background will be
      * drawn over it or a wipe-off brush will be used to reveal the background when the state is
-     * [PlaceholderState.isWipeOff].
+     * [PlaceholderState.isWipingOff].
      *
      * @param placeholderState the state of the placeholder
-     * @param painter the original painter that will be drawn over when in placeholder mode.
+     * @param originalPainter the original painter that will be drawn over when in placeholder mode.
      * @param color the color to use for the placeholder background brush
      */
     @Composable
     fun painterWithPlaceholderOverlayBackgroundBrush(
         placeholderState: PlaceholderState,
-        painter: Painter,
+        originalPainter: Painter,
         color: Color = MaterialTheme.colorScheme.surfaceContainer,
     ): Painter {
-        return if (!placeholderState.isShowContent) {
+        return if (!placeholderState.isHidden) {
             PlaceholderBackgroundPainter(
-                painter = painter,
+                painter = originalPainter,
                 placeholderState = placeholderState,
                 color = color
             )
         } else {
-            painter
+            originalPainter
         }
     }
 
     /**
      * Create a [Painter] that paints with a placeholder background brush. If the [placeholderState]
-     * is [PlaceholderState.isShowContent] then a transparent background will be shown. Otherwise a
+     * is [PlaceholderState.isHidden] then a transparent background will be shown. Otherwise a
      * placeholder background will be drawn or a wipe-off brush will be used to reveal the content
-     * underneath when [PlaceholderState.isWipeOff] is true.
+     * underneath when [PlaceholderState.isWipingOff] is true.
      *
      * @param placeholderState the state of the placeholder
      * @param color the color to use for the placeholder background brush
@@ -418,8 +418,11 @@
      */
     internal var backgroundOffset: Offset = Offset.Zero
 
-    /** Start the animation of the placeholder state. */
-    suspend fun startPlaceholderAnimation() {
+    /**
+     * Animate the placeholder according to the placeholder state. Cancels when the placeholder
+     * becomes inactive.
+     */
+    suspend fun animatePlaceholder() {
         if (!isReduceMotionEnabled) {
             coroutineScope {
                 while (isActive) {
@@ -430,7 +433,7 @@
     }
 
     /**
-     * The current value of the placeholder wipe-off visual effect gradient progression. The
+     * The current value of the placeholder wipe-off visual effect gradient progression in Px. The
      * progression is a 45 degree angle sweep across the whole screen running from outside of the
      * Top|Left of the screen to Bottom|Right used as the anchor for wipe-off gradient effects.
      *
@@ -439,8 +442,7 @@
      * of height/width to create a 45 degree angle) * 1.75f and progress to the
      * maximumScreenDimension * 0.75f.
      *
-     * The time taken for this progression to reach the edge of visible screen is
-     * [PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS]
+     * The time taken for this progression to reach the edge of visible screen is 300ms.
      */
     internal val placeholderWipeOffProgression: Float by derivedStateOf {
         val absoluteProgression =
@@ -461,7 +463,7 @@
      * gradient that flows across the screen. The progression will start at -maxScreenDimension (max
      * of height/width to create a 45 degree angle) and progress to the maximumScreenDimension.
      *
-     * The time taken for this progression is [PLACEHOLDER_WIPE_OFF_PROGRESSION_ALPHA_DURATION_MS]
+     * The time taken for this progression is 80ms.
      */
     internal val placeholderWipeOffAlpha: Float by derivedStateOf {
         val absoluteProgression =
@@ -475,12 +477,12 @@
     }
 
     /**
-     * The current value of the placeholder visual effect gradient progression. The progression
-     * gives the x coordinate to be applied to the placeholder gradient as it moves across the
-     * screen. Starting off screen to the left and progressing across the screen and finishing off
-     * the screen to the right after [PLACEHOLDER_SHIMMER_DURATION_MS].
+     * The current value of the placeholder visual effect gradient progression in Px. The
+     * progression gives the x coordinate to be applied to the placeholder gradient as it moves
+     * across the screen. Starting off screen to the left and progressing across the screen and
+     * finishing off the screen to the after 800ms.
      */
-    val placeholderProgression: Float by derivedStateOf {
+    internal val placeholderShimmerProgression: Float by derivedStateOf {
         val absoluteProgression =
             (frameMillis.longValue
                 .mod(PLACEHOLDER_SHIMMER_GAP_BETWEEN_ANIMATION_LOOPS_MS)
@@ -493,7 +495,7 @@
     /**
      * The current value of the placeholder visual effect gradient progression alpha/opacity. The
      * progression gives the alpha to apply during the period of the placeholder effect. This allows
-     * the effect to be faded in and then out during the [PLACEHOLDER_SHIMMER_DURATION_MS].
+     * the effect to be faded in and then out during 800ms.
      */
     internal val placeholderShimmerAlpha: Float by derivedStateOf {
         val absoluteProgression =
@@ -514,7 +516,7 @@
     /**
      * The current value of the placeholder visual effect gradient progression alpha/opacity during
      * the fade-in part of reset placeholder animation. This allows the effect to be faded in during
-     * the [PLACEHOLDER_RESET_ANIMATION_DURATION_MS].
+     * 450ms.
      */
     internal val resetPlaceholderFadeInAlpha: Float by derivedStateOf {
         val absoluteProgression =
@@ -534,7 +536,7 @@
     /**
      * The current value of the placeholder visual effect gradient progression alpha/opacity during
      * the fade-out part of reset placeholder animation. This allows the effect to be faded out
-     * during the [PLACEHOLDER_RESET_ANIMATION_DURATION_MS].
+     * during 450ms.
      */
     internal val resetPlaceholderFadeOutAlpha: Float by derivedStateOf {
         val absoluteProgression =
@@ -549,15 +551,13 @@
      * Returns true if the placeholder content should be shown with no placeholders effects and
      * false if either the placeholder or the wipe-off effect are being shown.
      */
-    val isShowContent: Boolean by derivedStateOf {
-        placeholderStage == PlaceholderStage.ShowContent
-    }
+    val isHidden: Boolean by derivedStateOf { placeholderStage == PlaceholderStage.HidePlaceholder }
 
     /**
-     * Should only be called when [isShowContent] is false. Returns true if the wipe-off effect that
-     * reveals content should be shown and false if the placeholder effect should be shown.
+     * Returns true if the wipe-off effect that reveals content is being shown and false if the
+     * placeholder effect should be shown.
      */
-    val isWipeOff: Boolean by derivedStateOf { placeholderStage == PlaceholderStage.WipeOff }
+    val isWipingOff: Boolean by derivedStateOf { placeholderStage == PlaceholderStage.WipeOff }
 
     /**
      * The width of the gradient to use for the placeholder shimmer and wipe-off effects. This is
@@ -567,7 +567,7 @@
     internal val gradientXYWidth: Float by derivedStateOf { maxScreenDimension * 2f.pow(1.5f) }
 
     internal var placeholderStage: PlaceholderStage =
-        if (isContentReady.value.invoke()) PlaceholderStage.ShowContent
+        if (isContentReady.value.invoke()) PlaceholderStage.HidePlaceholder
         else PlaceholderStage.ShowPlaceholder
         get() =
             derivedStateOf {
@@ -581,12 +581,12 @@
                                 (frameMillis.longValue - startOfWipeOffAnimation) >=
                                     PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS
                             ) {
-                                field = PlaceholderStage.ShowContent
+                                field = PlaceholderStage.HidePlaceholder
                             }
                             // Placeholder
                         } else if (isContentReady.value()) {
                             if (isReduceMotionEnabled) {
-                                field = PlaceholderStage.ShowContent
+                                field = PlaceholderStage.HidePlaceholder
                             } else {
                                 startOfWipeOffAnimation = frameMillis.longValue
                                 field = PlaceholderStage.WipeOff
@@ -652,13 +652,14 @@
 
         /**
          * Indicates that placeholders no longer to be shown. Enter this stage from [WipeOff] in the
-         * loop after the wire-off animation.
+         * loop after the wipe-off animation.
          */
-        val ShowContent = PlaceholderStage(2)
+        val HidePlaceholder = PlaceholderStage(2)
 
         /**
          * Resets the component to remove the content and reinstate the placeholders so that new
-         * content can be loaded. Enter this stage from [ShowContent] and exit to [ShowPlaceholder].
+         * content can be loaded. Enter this stage from [HidePlaceholder] and exit to
+         * [ShowPlaceholder].
          */
         val ResetContent = PlaceholderStage(3)
     }
@@ -668,7 +669,7 @@
             ShowPlaceholder -> "PlaceholderStage.ShowPlaceholder"
             WipeOff -> "PlaceholderStage.WipeOff"
             ResetContent -> "PlaceholderStage.ResetContent"
-            else -> "PlaceholderStage.ShowContent"
+            else -> "PlaceholderStage.HidePlaceholder"
         }
     }
 }
@@ -992,13 +993,23 @@
             Brush.linearGradient(
                 start =
                     Offset(
-                        x = placeholderState.placeholderProgression - halfGradientWidth - offset.x,
-                        y = placeholderState.placeholderProgression - halfGradientWidth - offset.y
+                        x =
+                            placeholderState.placeholderShimmerProgression -
+                                halfGradientWidth -
+                                offset.x,
+                        y =
+                            placeholderState.placeholderShimmerProgression -
+                                halfGradientWidth -
+                                offset.y
                     ),
                 end =
                     Offset(
-                        x = placeholderState.placeholderProgression + halfGradientWidth - offset.x,
-                        y = placeholderState.placeholderProgression + halfGradientWidth - offset.y
+                        x =
+                            placeholderState.placeholderShimmerProgression + halfGradientWidth -
+                                offset.x,
+                        y =
+                            placeholderState.placeholderShimmerProgression + halfGradientWidth -
+                                offset.y
                     ),
                 colorStops =
                     listOf(
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt
index b5f891f..e846a05 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt
@@ -17,7 +17,7 @@
 package androidx.wear.compose.material3
 
 import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.tween
+import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.Interaction
@@ -57,7 +57,6 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.material3.tokens.MotionTokens
 import androidx.wear.compose.material3.tokens.RadioButtonTokens
 import androidx.wear.compose.material3.tokens.ShapeTokens
 import androidx.wear.compose.material3.tokens.SplitRadioButtonTokens
@@ -1418,12 +1417,8 @@
         dotColor = color,
         onClick = null,
         interactionSource = null,
-        dotRadiusProgressDuration = { isSelected ->
-            if (isSelected) MotionTokens.DurationMedium1 else MotionTokens.DurationShort3
-        },
-        dotAlphaProgressDuration = MotionTokens.DurationShort3,
-        dotAlphaProgressDelay = MotionTokens.DurationShort2,
-        easing = MotionTokens.EasingStandardDecelerate,
+        dotRadiusAnimationSpec = PROGRESS_ANIMATION_SPEC,
+        dotAlphaAnimationSpec = PROGRESS_ANIMATION_SPEC,
         width = CONTROL_WIDTH,
         height = CONTROL_HEIGHT,
         ripple = ripple()
@@ -1443,8 +1438,10 @@
     }
 }
 
-private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
-    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
+private val COLOR_ANIMATION_SPEC: AnimationSpec<Color>
+    @Composable get() = MaterialTheme.motionScheme.slowEffectsSpec()
+private val PROGRESS_ANIMATION_SPEC: FiniteAnimationSpec<Float>
+    @Composable get() = MaterialTheme.motionScheme.fastEffectsSpec()
 private val SELECTION_CONTROL_WIDTH = 32.dp
 private val SELECTION_CONTROL_HEIGHT = 24.dp
 private val SELECTION_CONTROL_SPACING = 6.dp
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RoundButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RoundButton.kt
index b2be46e..7a4cd99 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RoundButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RoundButton.kt
@@ -35,7 +35,6 @@
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.withFrameMillis
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
@@ -211,15 +210,4 @@
     }
 }
 
-private suspend fun waitUntil(condition: () -> Boolean) {
-    val initialTimeMillis = withFrameMillis { it }
-    while (!condition()) {
-        val timeMillis = withFrameMillis { it }
-        if (timeMillis - initialTimeMillis > MAX_WAIT_TIME_MILLIS) return
-    }
-    return
-}
-
-private const val MAX_WAIT_TIME_MILLIS = 1_000L
-
 private const val MIN_REQUIRED_ANIMATION_PROGRESS = 0.75f
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt
index cd792cf..dc91159 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt
@@ -17,9 +17,8 @@
 package androidx.wear.compose.material3
 
 import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.TweenSpec
+import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.animation.core.animateFloat
-import androidx.compose.animation.core.tween
 import androidx.compose.animation.core.updateTransition
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
@@ -66,7 +65,6 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.lerp
-import androidx.wear.compose.material3.tokens.MotionTokens
 import androidx.wear.compose.material3.tokens.ShapeTokens
 import androidx.wear.compose.material3.tokens.SplitSwitchButtonTokens
 import androidx.wear.compose.material3.tokens.SwitchButtonTokens
@@ -1940,7 +1938,7 @@
 private val SPLIT_MIN_WIDTH = 48.dp
 private val SPLIT_SECTIONS_SHAPE = ShapeTokens.CornerExtraSmall
 
-private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
-    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
-private val SWITCH_PROGRESS_ANIMATION_SPEC: TweenSpec<Float> =
-    tween(MotionTokens.DurationMedium2, 0, MotionTokens.EasingStandardDecelerate)
+private val COLOR_ANIMATION_SPEC: AnimationSpec<Color>
+    @Composable get() = MaterialTheme.motionScheme.slowEffectsSpec()
+private val SWITCH_PROGRESS_ANIMATION_SPEC: FiniteAnimationSpec<Float>
+    @Composable get() = MaterialTheme.motionScheme.fastEffectsSpec()
diff --git a/wear/compose/compose-material3/src/main/res/values-af/strings.xml b/wear/compose/compose-material3/src/main/res/values-af/strings.xml
index 3ab44cf..4d7a998 100644
--- a/wear/compose/compose-material3/src/main/res/values-af/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-af/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Vermeerder"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Verminder"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Vermeerder"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Het misluk"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Sukses"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Maak op foon oop"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-am/strings.xml b/wear/compose/compose-material3/src/main/res/values-am/strings.xml
index 8897e0b..d3c755b 100644
--- a/wear/compose/compose-material3/src/main/res/values-am/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-am/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"ጨምር"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"ቀንስ"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"ጨምር"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"አልተሳካም"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"ተሳክቷል"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ስልክ ላይ ክፈት"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ar/strings.xml b/wear/compose/compose-material3/src/main/res/values-ar/strings.xml
index da562e4..02c4b8d 100644
--- a/wear/compose/compose-material3/src/main/res/values-ar/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ar/strings.xml
@@ -54,6 +54,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"زيادة"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"تقليل"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"زيادة"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"تعذر الإجراء"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"نجحَ الإجراء"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"فتح على الهاتف"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-as/strings.xml b/wear/compose/compose-material3/src/main/res/values-as/strings.xml
index 1a3d0b6..0b775bb 100644
--- a/wear/compose/compose-material3/src/main/res/values-as/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-as/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"বঢ়াওক"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"কমাওক"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"বঢ়াওক"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"বিফল হৈছে"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"সফল"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ফ’নত খোলক"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-az/strings.xml b/wear/compose/compose-material3/src/main/res/values-az/strings.xml
index 2116d76..a649f33 100644
--- a/wear/compose/compose-material3/src/main/res/values-az/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-az/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Artırın"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Azaldın"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Artırın"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Alınmadı"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Alındı"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Telefonda aç"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-b+sr+Latn/strings.xml b/wear/compose/compose-material3/src/main/res/values-b+sr+Latn/strings.xml
index 83aaef1..cc50b58 100644
--- a/wear/compose/compose-material3/src/main/res/values-b+sr+Latn/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-b+sr+Latn/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Povećaj"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Smanji"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Povećaj"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Nije uspelo"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Uspelo"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Na telefonu"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-be/strings.xml b/wear/compose/compose-material3/src/main/res/values-be/strings.xml
index 3504095..44a1d7a 100644
--- a/wear/compose/compose-material3/src/main/res/values-be/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-be/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Павялічыць"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Паменшыць"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Павялічыць"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Памылка"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Выканана"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"На тэлефоне"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-bg/strings.xml b/wear/compose/compose-material3/src/main/res/values-bg/strings.xml
index a0d9411..5741a7c 100644
--- a/wear/compose/compose-material3/src/main/res/values-bg/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-bg/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Увеличаване"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Намаляване"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Увеличаване"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Неуспешно"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Успешно"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Отв. на тел."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-bn/strings.xml b/wear/compose/compose-material3/src/main/res/values-bn/strings.xml
index af0fb65..9ee49c4 100644
--- a/wear/compose/compose-material3/src/main/res/values-bn/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-bn/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"বাড়ান"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"কমানো"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"বাড়ানো"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"সফল হয়নি"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"সফল হয়েছে"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ফোনে খুলুন"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-bs/strings.xml b/wear/compose/compose-material3/src/main/res/values-bs/strings.xml
index 1c2416d..3f986f8 100644
--- a/wear/compose/compose-material3/src/main/res/values-bs/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-bs/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Povećavanje"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Smanjenje"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Povećanje"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Neuspješno"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Uspješno"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Otvor. na tel."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ca/strings.xml b/wear/compose/compose-material3/src/main/res/values-ca/strings.xml
index 1376675..4f4240a 100644
--- a/wear/compose/compose-material3/src/main/res/values-ca/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ca/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Augmenta"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Disminueix"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Augmenta"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Ha fallat"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Correcte"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Obre al telèfon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-cs/strings.xml b/wear/compose/compose-material3/src/main/res/values-cs/strings.xml
index a914697..33664db 100644
--- a/wear/compose/compose-material3/src/main/res/values-cs/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-cs/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Zvýšit"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Snížit"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Zvýšit"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Nezdařilo se"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Hotovo"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Otevřít v telefonu"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-da/strings.xml b/wear/compose/compose-material3/src/main/res/values-da/strings.xml
index 5737e13..842214a 100644
--- a/wear/compose/compose-material3/src/main/res/values-da/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-da/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Øg"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Sænk"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Øg"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Mislykket"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Gennemført"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Åbn på telefon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-de/strings.xml b/wear/compose/compose-material3/src/main/res/values-de/strings.xml
index b763f40..875685b 100644
--- a/wear/compose/compose-material3/src/main/res/values-de/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-de/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Erhöhen"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Verringern"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Erhöhen"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Fehlgeschlagen"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Abgeschlossen"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Auf Smartphone öffnen"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-el/strings.xml b/wear/compose/compose-material3/src/main/res/values-el/strings.xml
index e0be921..2fb649b 100644
--- a/wear/compose/compose-material3/src/main/res/values-el/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-el/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Αύξηση"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Μείωση"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Αύξηση"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Αποτυχία"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Επιτυχία"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Στο τηλέφωνο"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-en-rAU/strings.xml b/wear/compose/compose-material3/src/main/res/values-en-rAU/strings.xml
index 272e741..b83a6af3 100644
--- a/wear/compose/compose-material3/src/main/res/values-en-rAU/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-en-rAU/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Increase"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Decrease"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Increase"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Failed"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Success"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Open on phone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-en-rCA/strings.xml b/wear/compose/compose-material3/src/main/res/values-en-rCA/strings.xml
index a1f8f19..33c33d5 100644
--- a/wear/compose/compose-material3/src/main/res/values-en-rCA/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-en-rCA/strings.xml
@@ -42,6 +42,8 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Increase"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Decrease"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Increase"</string>
+    <string name="wear_m3c_alert_dialog_content_description_confirm_button" msgid="7776845597891182382">"Confirm"</string>
+    <string name="wear_m3c_alert_dialog_content_description_dismiss_button" msgid="3572467833850785688">"Dismiss"</string>
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Failed"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Success"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Open on phone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-en-rGB/strings.xml b/wear/compose/compose-material3/src/main/res/values-en-rGB/strings.xml
index 272e741..b83a6af3 100644
--- a/wear/compose/compose-material3/src/main/res/values-en-rGB/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-en-rGB/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Increase"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Decrease"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Increase"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Failed"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Success"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Open on phone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-en-rIN/strings.xml b/wear/compose/compose-material3/src/main/res/values-en-rIN/strings.xml
index 272e741..b83a6af3 100644
--- a/wear/compose/compose-material3/src/main/res/values-en-rIN/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-en-rIN/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Increase"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Decrease"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Increase"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Failed"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Success"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Open on phone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-es-rUS/strings.xml b/wear/compose/compose-material3/src/main/res/values-es-rUS/strings.xml
index 74e4311..56c5f4f 100644
--- a/wear/compose/compose-material3/src/main/res/values-es-rUS/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-es-rUS/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumentar"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Disminuir"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumentar"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Error"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Listo"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Abrir en el teléfono"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-es/strings.xml b/wear/compose/compose-material3/src/main/res/values-es/strings.xml
index a3f0fb8..1a99712 100644
--- a/wear/compose/compose-material3/src/main/res/values-es/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-es/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumentar"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Reducir"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumentar"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Error"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Todo correcto"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Ábrelo en el teléfono"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-et/strings.xml b/wear/compose/compose-material3/src/main/res/values-et/strings.xml
index abb3ac0..8d80314 100644
--- a/wear/compose/compose-material3/src/main/res/values-et/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-et/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Suurenda"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Vähenda"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Suurenda"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Ebaõnnestus"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Õnnestus"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Ava telefonis"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-eu/strings.xml b/wear/compose/compose-material3/src/main/res/values-eu/strings.xml
index a44067d..76fc614 100644
--- a/wear/compose/compose-material3/src/main/res/values-eu/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-eu/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Igo"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Jaitsi"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Igo"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Huts egin du"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Eginda"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Ireki telefonoan"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-fa/strings.xml b/wear/compose/compose-material3/src/main/res/values-fa/strings.xml
index 4ae1008..ecf3999 100644
--- a/wear/compose/compose-material3/src/main/res/values-fa/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-fa/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"افزایش دادن"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"کاهش دادن"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"افزایش دادن"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"انجام نشد"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"انجام شد"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"باز کردن در تلفن"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-fi/strings.xml b/wear/compose/compose-material3/src/main/res/values-fi/strings.xml
index 824c7b5..c704c03 100644
--- a/wear/compose/compose-material3/src/main/res/values-fi/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-fi/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Lisää"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Vähennä"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Lisää"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Epäonnistui"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Onnistui"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Puhelimella"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-fr-rCA/strings.xml b/wear/compose/compose-material3/src/main/res/values-fr-rCA/strings.xml
index 6aae002..f6fa0fe 100644
--- a/wear/compose/compose-material3/src/main/res/values-fr-rCA/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-fr-rCA/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Augmenter"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Diminuer"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Augmenter"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Échec"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Réussite"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Ouv. ds tél."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-fr/strings.xml b/wear/compose/compose-material3/src/main/res/values-fr/strings.xml
index f8cfafe..6cd5c75 100644
--- a/wear/compose/compose-material3/src/main/res/values-fr/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-fr/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Augmenter"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Diminuer"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Augmenter"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Échec"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Opération réussie"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Ouvrir sur le téléphone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-gl/strings.xml b/wear/compose/compose-material3/src/main/res/values-gl/strings.xml
index c22ed45..985b2f3 100644
--- a/wear/compose/compose-material3/src/main/res/values-gl/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-gl/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumentar"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Reducir"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumentar"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Erro"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Todo correcto"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Abrir no tel."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-gu/strings.xml b/wear/compose/compose-material3/src/main/res/values-gu/strings.xml
index 92e9105..5d9c5073 100644
--- a/wear/compose/compose-material3/src/main/res/values-gu/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-gu/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"વધારો"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"ઘટાડો"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"વધારો"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"નિષ્ફળ થઈ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"સફળ થઈ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ફોન પર ખોલો"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-hi/strings.xml b/wear/compose/compose-material3/src/main/res/values-hi/strings.xml
index cafe258..b50a062 100644
--- a/wear/compose/compose-material3/src/main/res/values-hi/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-hi/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"बढ़ाएं"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"घटाएं"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"बढ़ाएं"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"काम नहीं हुआ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"काम हो गया"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"फ़ोन पर खोलें"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-hr/strings.xml b/wear/compose/compose-material3/src/main/res/values-hr/strings.xml
index 754b6b6..1d6cdd0 100644
--- a/wear/compose/compose-material3/src/main/res/values-hr/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-hr/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Povećaj"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Smanji"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Povećaj"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Nije uspjelo"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Uspjeh"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Na telefonu"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-hu/strings.xml b/wear/compose/compose-material3/src/main/res/values-hu/strings.xml
index 167ca98..c9cf8e1 100644
--- a/wear/compose/compose-material3/src/main/res/values-hu/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-hu/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Növelés"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Csökkentés"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Növelés"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Sikertelen"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Sikerült"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Nyissa meg mobilon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-hy/strings.xml b/wear/compose/compose-material3/src/main/res/values-hy/strings.xml
index c2b9640..1edfa943 100644
--- a/wear/compose/compose-material3/src/main/res/values-hy/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-hy/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Ավելացնել"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Իջեցնել"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Բարձրացնել"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Ձախողվել է"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Պատրաստ է"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Բացեք հեռախոսում"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-in/strings.xml b/wear/compose/compose-material3/src/main/res/values-in/strings.xml
index 2edf41c..82f3c6e 100644
--- a/wear/compose/compose-material3/src/main/res/values-in/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-in/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Tingkatkan"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Turunkan"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Tingkatkan"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Gagal"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Berhasil"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Buka di ponsel"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-is/strings.xml b/wear/compose/compose-material3/src/main/res/values-is/strings.xml
index a8654ef..494885e 100644
--- a/wear/compose/compose-material3/src/main/res/values-is/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-is/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Auka"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Lækka"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Hækka"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Mistókst"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Tókst"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Opna í símanum"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-it/strings.xml b/wear/compose/compose-material3/src/main/res/values-it/strings.xml
index 1604a5f..dbb4bdf 100644
--- a/wear/compose/compose-material3/src/main/res/values-it/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-it/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumenta"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Riduci"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumenta"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Non riuscita"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Riuscita"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Su smartph."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-iw/strings.xml b/wear/compose/compose-material3/src/main/res/values-iw/strings.xml
index 0a0b1cd..27bb9c0 100644
--- a/wear/compose/compose-material3/src/main/res/values-iw/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-iw/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"הגברה"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"הפחתה"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"העלאה"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"הפעולה נכשלה"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"הפעולה הצליחה"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"פתיחה בטלפון"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ja/strings.xml b/wear/compose/compose-material3/src/main/res/values-ja/strings.xml
index d7ac4f2c..e0d13b8 100644
--- a/wear/compose/compose-material3/src/main/res/values-ja/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ja/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"上げる"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"減らす"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"増やす"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"失敗"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"成功"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"スマホで開く"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ka/strings.xml b/wear/compose/compose-material3/src/main/res/values-ka/strings.xml
index deda66ae..87a5202 100644
--- a/wear/compose/compose-material3/src/main/res/values-ka/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ka/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"გაზრდა"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"შემცირება"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"გაზრდა"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ვერ შესრულდა"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"შესრულდა"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ტელეფონში გახსნა"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-kk/strings.xml b/wear/compose/compose-material3/src/main/res/values-kk/strings.xml
index e3e7615..8af1496 100644
--- a/wear/compose/compose-material3/src/main/res/values-kk/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-kk/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Көбейту"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Азайту"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Көбейту"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Расталмады."</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Расталды."</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Телефоннан ашыңыз."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-km/strings.xml b/wear/compose/compose-material3/src/main/res/values-km/strings.xml
index 83ca8d5..4ce6dc5 100644
--- a/wear/compose/compose-material3/src/main/res/values-km/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-km/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"បង្កើន"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"បន្ថយ"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"បង្កើន"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"មិនបានសម្រេច"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"ជោគជ័យ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"បើកលើទូរសព្ទ"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-kn/strings.xml b/wear/compose/compose-material3/src/main/res/values-kn/strings.xml
index 447dc4d..c0bcb1c 100644
--- a/wear/compose/compose-material3/src/main/res/values-kn/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-kn/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"ಹೆಚ್ಚಿಸಿ"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"ಕಡಿಮೆ ಮಾಡಿ"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"ಹೆಚ್ಚಿಸಿ"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ವಿಫಲವಾಗಿದೆ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"ಯಶಸ್ವಿಯಾಗಿದೆ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ಫೋನ್‌ನಲ್ಲಿ ತೆರೆಯಿರಿ"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ko/strings.xml b/wear/compose/compose-material3/src/main/res/values-ko/strings.xml
index f30113a..3870de0 100644
--- a/wear/compose/compose-material3/src/main/res/values-ko/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ko/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"증가"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"줄이기"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"늘리기"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"실패"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"성공"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"휴대전화에서 열기"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ky/strings.xml b/wear/compose/compose-material3/src/main/res/values-ky/strings.xml
index 4ffd0d3..9e0d4c0 100644
--- a/wear/compose/compose-material3/src/main/res/values-ky/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ky/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Жогорулатуу"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Төмөндөтүү"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Жогорулатуу"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Ишке ашпады"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Ийгилик"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Телефондо ачуу"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-lo/strings.xml b/wear/compose/compose-material3/src/main/res/values-lo/strings.xml
index 52e8a9b..774ced7 100644
--- a/wear/compose/compose-material3/src/main/res/values-lo/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-lo/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"ເພີ່ມຂຶ້ນ"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"ຫຼຸດລົງ"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"ເພີ່ມຂຶ້ນ"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ບໍ່ສຳເລັດ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"ສຳເລັດ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ເປີດໃນໂທລະສັບ"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-lt/strings.xml b/wear/compose/compose-material3/src/main/res/values-lt/strings.xml
index 28e19fe..5bd1303 100644
--- a/wear/compose/compose-material3/src/main/res/values-lt/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-lt/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Padidinti"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Sumažinti"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Padidinti"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Nepavyko"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Pavyko"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Atidaryti telefone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-lv/strings.xml b/wear/compose/compose-material3/src/main/res/values-lv/strings.xml
index 94d0107..f355546 100644
--- a/wear/compose/compose-material3/src/main/res/values-lv/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-lv/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Palielināt"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Samazināt"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Palielināt"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Neizdevās"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Izdevās"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Atvērt tālrunī"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-mk/strings.xml b/wear/compose/compose-material3/src/main/res/values-mk/strings.xml
index f2cd97d..3f556e4 100644
--- a/wear/compose/compose-material3/src/main/res/values-mk/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-mk/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Зголеми"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Намалување"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Зголемување"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Неуспешно"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Успешно"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Отвори на телефонот"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ml/strings.xml b/wear/compose/compose-material3/src/main/res/values-ml/strings.xml
index 4d26863..632c921 100644
--- a/wear/compose/compose-material3/src/main/res/values-ml/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ml/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"കൂട്ടുക"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"കുറയ്‌ക്കുക"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"കൂട്ടുക"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"പരാജയപ്പെട്ടു"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"വിജയിച്ചു"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ഫോണിൽ തുറക്കൂ"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-mn/strings.xml b/wear/compose/compose-material3/src/main/res/values-mn/strings.xml
index 3b24ce1..582aa3a 100644
--- a/wear/compose/compose-material3/src/main/res/values-mn/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-mn/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Нэмэгдүүлэх"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Багасгах"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Нэмэгдүүлэх"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Амжилтгүй"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Амжилттай"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Утсанд нээх"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-mr/strings.xml b/wear/compose/compose-material3/src/main/res/values-mr/strings.xml
index e6efee5..acbfd1c 100644
--- a/wear/compose/compose-material3/src/main/res/values-mr/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-mr/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"वाढवा"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"कमी करा"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"वाढवा"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"अयशस्वी"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"यशस्वी झाले"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"फोनवर उघडा"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ms/strings.xml b/wear/compose/compose-material3/src/main/res/values-ms/strings.xml
index b41938c..9a77a5d 100644
--- a/wear/compose/compose-material3/src/main/res/values-ms/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ms/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Tambahkan"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Kurangkan"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Tambahkan"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Gagal"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Berjaya"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Buka pada telefon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-my/strings.xml b/wear/compose/compose-material3/src/main/res/values-my/strings.xml
index 678ad76..da6e684 100644
--- a/wear/compose/compose-material3/src/main/res/values-my/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-my/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"တိုးရန်"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"လျှော့ရန်"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"ချဲ့ရန်"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"မအောင်မြင်ပါ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"အောင်မြင်သည်"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ဖုန်း၌ဖွင့်ရန်"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-nb/strings.xml b/wear/compose/compose-material3/src/main/res/values-nb/strings.xml
index 664750c..ef7e2f0 100644
--- a/wear/compose/compose-material3/src/main/res/values-nb/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-nb/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Øk"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Reduser"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Øk"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Mislyktes"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Vellykket"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Åpne på tlf."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ne/strings.xml b/wear/compose/compose-material3/src/main/res/values-ne/strings.xml
index fe60e64..fd2cf9b 100644
--- a/wear/compose/compose-material3/src/main/res/values-ne/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ne/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"बढाउनुहोस्"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"घटाउनुहोस्"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"बढाउनुहोस्"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"पुष्टि गर्न सकिएन"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"पुष्टि गरियो"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"फोनमा खोल्नुहोस्"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-nl/strings.xml b/wear/compose/compose-material3/src/main/res/values-nl/strings.xml
index a267de1..34beeaa 100644
--- a/wear/compose/compose-material3/src/main/res/values-nl/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-nl/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Verhogen"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Verlagen"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Verhogen"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Mislukt"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Geslaagd"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Openen op telefoon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-or/strings.xml b/wear/compose/compose-material3/src/main/res/values-or/strings.xml
index d356304..1b9346e 100644
--- a/wear/compose/compose-material3/src/main/res/values-or/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-or/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"ବଢ଼ାନ୍ତୁ"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"କମାନ୍ତୁ"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"ବଢ଼ାନ୍ତୁ"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ବିଫଳ ହୋଇଛି"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"ସଫଳ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ଫୋନରେ ଖୋଲନ୍ତୁ"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-pa/strings.xml b/wear/compose/compose-material3/src/main/res/values-pa/strings.xml
index 3c68908..96306b7 100644
--- a/wear/compose/compose-material3/src/main/res/values-pa/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-pa/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"ਵਧਾਓ"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"ਘਟਾਓ"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"ਵਧਾਓ"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ਅਸਫਲ ਰਿਹਾ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"ਸਫਲ ਰਿਹਾ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ਫ਼ੋਨ \'ਤੇ ਖੋਲ੍ਹੋ"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-pl/strings.xml b/wear/compose/compose-material3/src/main/res/values-pl/strings.xml
index a9249328..fecfbf7 100644
--- a/wear/compose/compose-material3/src/main/res/values-pl/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-pl/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Zwiększ"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Zmniejsz"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Zwiększ"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Niepowodzenie"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Udało się"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Otwórz na telefonie"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-pt-rBR/strings.xml b/wear/compose/compose-material3/src/main/res/values-pt-rBR/strings.xml
index 775ebcb..e5ab9320 100644
--- a/wear/compose/compose-material3/src/main/res/values-pt-rBR/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-pt-rBR/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumentar"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Diminuir"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumentar"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Falha"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Pronto"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Abra no smartphone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-pt-rPT/strings.xml b/wear/compose/compose-material3/src/main/res/values-pt-rPT/strings.xml
index a99c8c1..15c07d1 100644
--- a/wear/compose/compose-material3/src/main/res/values-pt-rPT/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-pt-rPT/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumentar"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Diminuir"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumentar"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Falhou"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Concluído"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Abrir no tel."</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-pt/strings.xml b/wear/compose/compose-material3/src/main/res/values-pt/strings.xml
index 775ebcb..e5ab9320 100644
--- a/wear/compose/compose-material3/src/main/res/values-pt/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-pt/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Aumentar"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Diminuir"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Aumentar"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Falha"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Pronto"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Abra no smartphone"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ro/strings.xml b/wear/compose/compose-material3/src/main/res/values-ro/strings.xml
index b2920e2..8e21c1b 100644
--- a/wear/compose/compose-material3/src/main/res/values-ro/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ro/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Crește"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Scade"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Crește"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Eroare"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Succes"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Pe telefon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ru/strings.xml b/wear/compose/compose-material3/src/main/res/values-ru/strings.xml
index 38b6613..bfa21739 100644
--- a/wear/compose/compose-material3/src/main/res/values-ru/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ru/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Увеличить"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Уменьшить"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Увеличить"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Ошибка"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Готово"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Открыть на телефоне"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-si/strings.xml b/wear/compose/compose-material3/src/main/res/values-si/strings.xml
index db2458b..37aa465 100644
--- a/wear/compose/compose-material3/src/main/res/values-si/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-si/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"වැඩි කරන්න"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"අඩු කරන්න"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"වැඩි කරන්න"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"අසමත් විය"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"සාර්ථකයි"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"දුරකථනයෙන් විවෘත කරන්න"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-sk/strings.xml b/wear/compose/compose-material3/src/main/res/values-sk/strings.xml
index 1569d57..30e57bb 100644
--- a/wear/compose/compose-material3/src/main/res/values-sk/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-sk/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Zvýšiť"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Znížiť"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Zvýšiť"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Neúspešné"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Podarilo sa"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Otvorte v telefóne"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-sl/strings.xml b/wear/compose/compose-material3/src/main/res/values-sl/strings.xml
index cb50296..54c0542 100644
--- a/wear/compose/compose-material3/src/main/res/values-sl/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-sl/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Povečanje"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Zmanjšaj"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Povečaj"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Neuspešno"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Uspešno"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Odpri v telefonu"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-sq/strings.xml b/wear/compose/compose-material3/src/main/res/values-sq/strings.xml
index 0ecac90..ba1133a 100644
--- a/wear/compose/compose-material3/src/main/res/values-sq/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-sq/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Rrit"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Ul"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Rrit"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Dështoi"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Me sukses"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Hape në telefon"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-sr/strings.xml b/wear/compose/compose-material3/src/main/res/values-sr/strings.xml
index 78c8d8c..44ef98d 100644
--- a/wear/compose/compose-material3/src/main/res/values-sr/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-sr/strings.xml
@@ -45,6 +45,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Повећај"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Смањи"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Повећај"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Није успело"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Успело"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"На телефону"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-sv/strings.xml b/wear/compose/compose-material3/src/main/res/values-sv/strings.xml
index c8d50d9..e388d545 100644
--- a/wear/compose/compose-material3/src/main/res/values-sv/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-sv/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Öka"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Minska"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Öka"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Misslyckades"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Klart"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"På telefonen"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-sw/strings.xml b/wear/compose/compose-material3/src/main/res/values-sw/strings.xml
index 78cb7e0..bbdd5f8 100644
--- a/wear/compose/compose-material3/src/main/res/values-sw/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-sw/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Ongeza"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Punguza"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Ongeza"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Imeshindwa"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Imemaliza"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Fungua kwenye simu"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ta/strings.xml b/wear/compose/compose-material3/src/main/res/values-ta/strings.xml
index b8952f2..18b4454 100644
--- a/wear/compose/compose-material3/src/main/res/values-ta/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ta/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"அதிகரிக்கும்"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"குறைக்கும்"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"அதிகரிக்கும்"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"தோல்வி"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"முடிந்தது"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"மொபைலில் திற"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-te/strings.xml b/wear/compose/compose-material3/src/main/res/values-te/strings.xml
index 3664364..b0ad3e6 100644
--- a/wear/compose/compose-material3/src/main/res/values-te/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-te/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"పెంచండి"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"తగ్గించండి"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"పెంచండి"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"విఫలమైంది"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"విజయవంతమైంది"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"ఫోన్‌లో తెరు"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-th/strings.xml b/wear/compose/compose-material3/src/main/res/values-th/strings.xml
index f82c0a5..fc10a30 100644
--- a/wear/compose/compose-material3/src/main/res/values-th/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-th/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"เพิ่ม"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"ลด"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"เพิ่ม"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ไม่สำเร็จ"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"สำเร็จ"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"เปิดในโทรศัพท์"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-tl/strings.xml b/wear/compose/compose-material3/src/main/res/values-tl/strings.xml
index c9781cd..c51056a 100644
--- a/wear/compose/compose-material3/src/main/res/values-tl/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-tl/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Dagdagan"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Bawasan"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Dagdagan"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Nabigo"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Matagumpay"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Buksan"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-tr/strings.xml b/wear/compose/compose-material3/src/main/res/values-tr/strings.xml
index e950de0..425a8af 100644
--- a/wear/compose/compose-material3/src/main/res/values-tr/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-tr/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Artır"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Azalt"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Artır"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Başarısız"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Başarılı"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Telefonda aç"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-uk/strings.xml b/wear/compose/compose-material3/src/main/res/values-uk/strings.xml
index 9c8f77f..b09239b 100644
--- a/wear/compose/compose-material3/src/main/res/values-uk/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-uk/strings.xml
@@ -48,6 +48,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Збільшити"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Зменшити"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Збільшити"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Помилка"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Готово"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"На телефоні"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-ur/strings.xml b/wear/compose/compose-material3/src/main/res/values-ur/strings.xml
index 4c82b62..a6c5a45 100644
--- a/wear/compose/compose-material3/src/main/res/values-ur/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-ur/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"بڑھائیں"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"کم کریں"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"بڑھائیں"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"ناکام ہوا"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"کامیاب"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"فون پر کھولیں"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-uz/strings.xml b/wear/compose/compose-material3/src/main/res/values-uz/strings.xml
index 3a0749d..038a7ef 100644
--- a/wear/compose/compose-material3/src/main/res/values-uz/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-uz/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Oshirish"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Pasaytirish"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Oshirish"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Bajarilmadi"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Bajarildi"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Telefonda"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-vi/strings.xml b/wear/compose/compose-material3/src/main/res/values-vi/strings.xml
index e1a9df8..5110168 100644
--- a/wear/compose/compose-material3/src/main/res/values-vi/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-vi/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Tăng"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Giảm"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Tăng"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Lỗi"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Thành công"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Mở trên điện thoại"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-zh-rCN/strings.xml b/wear/compose/compose-material3/src/main/res/values-zh-rCN/strings.xml
index 7f82188..bcbe3a2 100644
--- a/wear/compose/compose-material3/src/main/res/values-zh-rCN/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-zh-rCN/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"增加"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"降低"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"提高"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"失败"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"成功"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"在手机上打开"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-zh-rHK/strings.xml b/wear/compose/compose-material3/src/main/res/values-zh-rHK/strings.xml
index e87a261..7cedc50 100644
--- a/wear/compose/compose-material3/src/main/res/values-zh-rHK/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-zh-rHK/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"調高"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"調低"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"調高"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"失敗"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"成功"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"在手機開啟"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-zh-rTW/strings.xml b/wear/compose/compose-material3/src/main/res/values-zh-rTW/strings.xml
index 311e77d9..c330c20 100644
--- a/wear/compose/compose-material3/src/main/res/values-zh-rTW/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-zh-rTW/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"調高"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"調低"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"調高"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"失敗"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"成功"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"在手機上開啟"</string>
diff --git a/wear/compose/compose-material3/src/main/res/values-zu/strings.xml b/wear/compose/compose-material3/src/main/res/values-zu/strings.xml
index b71059a..d9b5dbc 100644
--- a/wear/compose/compose-material3/src/main/res/values-zu/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-zu/strings.xml
@@ -42,6 +42,10 @@
     <string name="wear_m3c_slider_increase_content_description" msgid="3329631766954416834">"Khulisa"</string>
     <string name="wear_m3c_stepper_decrease_content_description" msgid="6939134411425530620">"Yehlisa"</string>
     <string name="wear_m3c_stepper_increase_content_description" msgid="6513575827514139918">"Khulisa"</string>
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_confirm_button (7776845597891182382) -->
+    <skip />
+    <!-- no translation found for wear_m3c_alert_dialog_content_description_dismiss_button (3572467833850785688) -->
+    <skip />
     <string name="wear_m3c_confirmation_failure_message" msgid="6690105830380889949">"Yehlulekile"</string>
     <string name="wear_m3c_confirmation_success_message" msgid="7045594078216655038">"Impumelelo"</string>
     <string name="wear_m3c_open_on_phone" msgid="5829463187924353601">"Vula efonini"</string>
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ButtonBenchmarkBase.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ButtonBenchmarkBase.kt
index 9ba55cc..3fdfc12 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ButtonBenchmarkBase.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ButtonBenchmarkBase.kt
@@ -18,7 +18,9 @@
 
 import android.content.Intent
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.uiautomator.By
 import org.junit.After
@@ -26,6 +28,7 @@
 import org.junit.Rule
 import org.junit.Test
 
+@OptIn(ExperimentalMetricApi::class)
 abstract class ButtonBenchmarkBase(
     private val compilationMode: CompilationMode,
     private val activityAction: String
@@ -46,7 +49,8 @@
     fun start() {
         benchmarkRule.measureRepeated(
             packageName = PACKAGE_NAME,
-            metrics = listOf(FrameTimingMetric()),
+            metrics =
+                listOf(FrameTimingGfxInfoMetric(), MemoryUsageMetric(MemoryUsageMetric.Mode.Last)),
             compilationMode = compilationMode,
             iterations = 10,
             setupBlock = {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt
index 22b55a3..9662bfc 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt
@@ -18,7 +18,9 @@
 
 import android.content.Intent
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
 import androidx.test.uiautomator.By
@@ -32,6 +34,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
+@OptIn(ExperimentalMetricApi::class)
 @LargeTest
 @RunWith(Parameterized::class)
 class PositionIndicatorBenchmark(private val compilationMode: CompilationMode) {
@@ -51,7 +54,8 @@
     fun start() {
         benchmarkRule.measureRepeated(
             packageName = PACKAGE_NAME,
-            metrics = listOf(FrameTimingMetric()),
+            metrics =
+                listOf(FrameTimingGfxInfoMetric(), MemoryUsageMetric(MemoryUsageMetric.Mode.Last)),
             compilationMode = compilationMode,
             iterations = 5,
             setupBlock = {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt
index b3704cc..f357f35 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt
@@ -19,7 +19,9 @@
 import android.content.Intent
 import android.graphics.Point
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
 import androidx.test.uiautomator.By
@@ -31,6 +33,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
+@OptIn(ExperimentalMetricApi::class)
 @LargeTest
 @RunWith(Parameterized::class)
 class ScrollBenchmark(private val compilationMode: CompilationMode) {
@@ -50,7 +53,11 @@
     fun start() {
         benchmarkRule.measureRepeated(
             packageName = PACKAGE_NAME,
-            metrics = listOf(FrameTimingMetric()),
+            metrics =
+                listOf(
+                    FrameTimingGfxInfoMetric(),
+                    MemoryUsageMetric(MemoryUsageMetric.Mode.Last),
+                ),
             compilationMode = compilationMode,
             iterations = 10,
             setupBlock = {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt
index fc09578..4e4a9072 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt
@@ -18,7 +18,9 @@
 
 import android.content.Intent
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
 import androidx.test.uiautomator.By
@@ -31,6 +33,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
+@OptIn(ExperimentalMetricApi::class)
 @LargeTest
 @RunWith(Parameterized::class)
 class SwipeToDismissBenchmark(private val compilationMode: CompilationMode) {
@@ -50,7 +53,11 @@
     fun start() {
         benchmarkRule.measureRepeated(
             packageName = PACKAGE_NAME,
-            metrics = listOf(FrameTimingMetric()),
+            metrics =
+                listOf(
+                    FrameTimingGfxInfoMetric(),
+                    MemoryUsageMetric(MemoryUsageMetric.Mode.Last),
+                ),
             compilationMode = compilationMode,
             iterations = 10,
             setupBlock = {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt
index 9845b66..9786346 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt
@@ -18,7 +18,9 @@
 
 import android.content.Intent
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
 import androidx.test.uiautomator.By
@@ -31,6 +33,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
+@OptIn(ExperimentalMetricApi::class)
 @LargeTest
 @RunWith(Parameterized::class)
 class SwipeToRevealBenchmark(private val compilationMode: CompilationMode) {
@@ -50,7 +53,11 @@
     fun start() {
         benchmarkRule.measureRepeated(
             packageName = PACKAGE_NAME,
-            metrics = listOf(FrameTimingMetric()),
+            metrics =
+                listOf(
+                    FrameTimingGfxInfoMetric(),
+                    MemoryUsageMetric(MemoryUsageMetric.Mode.Last),
+                ),
             compilationMode = compilationMode,
             iterations = 10,
             setupBlock = {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/material3/DialogBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/material3/DialogBenchmark.kt
index 337bb62..fa6aa78 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/material3/DialogBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/material3/DialogBenchmark.kt
@@ -18,7 +18,9 @@
 
 import android.content.Intent
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.FrameTimingMetric
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
 import androidx.test.uiautomator.By
@@ -33,6 +35,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
+@OptIn(ExperimentalMetricApi::class)
 @LargeTest
 @RunWith(Parameterized::class)
 class DialogBenchmark(private val compilationMode: CompilationMode) {
@@ -52,7 +55,8 @@
     fun start() {
         benchmarkRule.measureRepeated(
             packageName = PACKAGE_NAME,
-            metrics = listOf(FrameTimingMetric()),
+            metrics =
+                listOf(FrameTimingGfxInfoMetric(), MemoryUsageMetric(MemoryUsageMetric.Mode.Last)),
             compilationMode = compilationMode,
             iterations = 5,
             setupBlock = {
diff --git a/wear/protolayout/protolayout-proto/src/main/proto/layout.proto b/wear/protolayout/protolayout-proto/src/main/proto/layout.proto
index 540382b..b235c5a 100644
--- a/wear/protolayout/protolayout-proto/src/main/proto/layout.proto
+++ b/wear/protolayout/protolayout-proto/src/main/proto/layout.proto
@@ -736,6 +736,45 @@
   Shadow shadow = 2;
 }
 
+// A dashed arc line that can be placed in an Arc container. It is an arc line made up of arc line
+// segments separated by gaps.
+message DashedArcLine {
+  // The length of this line in degrees, including gaps. <setter> If not defined,
+  // defaults to 0.</setter>
+  //
+  // When using a dynamic value, make sure to specify the bounding constraints
+  // for the affected layout element through {@code
+  // setLayoutConstraintsForDynamicLength(AngularLayoutConstraint)} otherwise
+  // {@code build()} fails.
+  DegreesProp length = 1;
+
+  // The thickness of this line. <setter> If not defined, defaults to 0.</setter>
+  DpProp thickness = 2;
+
+  // The color of this line.
+  ColorProp color = 3;
+
+  // Modifiers for this element.
+  ArcModifiers modifiers = 4;
+
+  // The direction in which this line is drawn.<setter> If not set, defaults to
+  // ARC_DIRECTION_CLOCKWISE.</setter>
+  ArcDirectionProp arc_direction = 5;
+
+  // The dashed line pattern which describes how the arc line is segmented by gaps.
+  DashedLinePattern line_pattern = 6;
+}
+
+// A dashed line pattern which describes how the dashed arc line is segmented by gaps.
+message DashedLinePattern {
+  // The size in dp of the gap between the line segments.<setter> If not
+  // defined, defaults to 0.</setter>
+  DpProp gap_size = 1;
+
+  // The list of each gap's center location in degrees.
+  repeated DegreesProp gap_locations = 2;
+}
+
 // A simple spacer used to provide padding between adjacent elements in an Arc.
 message ArcSpacer {
   // The length of this spacer, in degrees. If not defined, defaults to 0.
@@ -837,6 +876,7 @@
     ArcLine line = 2;
     ArcSpacer spacer = 3;
     ArcAdapter adapter = 4;
+    DashedArcLine dashed_line = 5;
   }
 }
 
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
index 3be0537..d8ed179 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
@@ -3961,6 +3961,10 @@
                                 parentViewWrapper, element.getText(), nodePosId, pipelineMaker);
                 break;
 
+            case DASHED_LINE:
+                // TODO: b/360314390 - inflate a dashed arc here with WearDashedArcLineView
+                break;
+
             case INNER_NOT_SET:
                 break;
         }
diff --git a/wear/protolayout/protolayout-testing/api/current.txt b/wear/protolayout/protolayout-testing/api/current.txt
index e6f50d0..dd57766 100644
--- a/wear/protolayout/protolayout-testing/api/current.txt
+++ b/wear/protolayout/protolayout-testing/api/current.txt
@@ -1 +1,25 @@
 // Signature format: 4.0
+package androidx.wear.protolayout.testing {
+
+  public final class LayoutElementAssertion {
+    method public androidx.wear.protolayout.testing.LayoutElementAssertion assert(androidx.wear.protolayout.testing.LayoutElementMatcher matcher);
+    method public void assertDoesNotExist();
+    method public void assertExists();
+  }
+
+  public final class LayoutElementAssertionsProvider {
+    ctor public LayoutElementAssertionsProvider(androidx.wear.protolayout.LayoutElementBuilders.Layout layout);
+    ctor public LayoutElementAssertionsProvider(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement layoutRoot);
+    method public androidx.wear.protolayout.testing.LayoutElementAssertion onElement(androidx.wear.protolayout.testing.LayoutElementMatcher matcher);
+    method public androidx.wear.protolayout.testing.LayoutElementAssertion onRoot();
+  }
+
+  public final class LayoutElementMatcher {
+    ctor public LayoutElementMatcher(String description, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.LayoutElementBuilders.LayoutElement,java.lang.Boolean> matcher);
+    method public infix androidx.wear.protolayout.testing.LayoutElementMatcher and(androidx.wear.protolayout.testing.LayoutElementMatcher other);
+    method public operator androidx.wear.protolayout.testing.LayoutElementMatcher not();
+    method public infix androidx.wear.protolayout.testing.LayoutElementMatcher or(androidx.wear.protolayout.testing.LayoutElementMatcher other);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-testing/api/restricted_current.txt b/wear/protolayout/protolayout-testing/api/restricted_current.txt
index e6f50d0..dd57766 100644
--- a/wear/protolayout/protolayout-testing/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-testing/api/restricted_current.txt
@@ -1 +1,25 @@
 // Signature format: 4.0
+package androidx.wear.protolayout.testing {
+
+  public final class LayoutElementAssertion {
+    method public androidx.wear.protolayout.testing.LayoutElementAssertion assert(androidx.wear.protolayout.testing.LayoutElementMatcher matcher);
+    method public void assertDoesNotExist();
+    method public void assertExists();
+  }
+
+  public final class LayoutElementAssertionsProvider {
+    ctor public LayoutElementAssertionsProvider(androidx.wear.protolayout.LayoutElementBuilders.Layout layout);
+    ctor public LayoutElementAssertionsProvider(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement layoutRoot);
+    method public androidx.wear.protolayout.testing.LayoutElementAssertion onElement(androidx.wear.protolayout.testing.LayoutElementMatcher matcher);
+    method public androidx.wear.protolayout.testing.LayoutElementAssertion onRoot();
+  }
+
+  public final class LayoutElementMatcher {
+    ctor public LayoutElementMatcher(String description, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.LayoutElementBuilders.LayoutElement,java.lang.Boolean> matcher);
+    method public infix androidx.wear.protolayout.testing.LayoutElementMatcher and(androidx.wear.protolayout.testing.LayoutElementMatcher other);
+    method public operator androidx.wear.protolayout.testing.LayoutElementMatcher not();
+    method public infix androidx.wear.protolayout.testing.LayoutElementMatcher or(androidx.wear.protolayout.testing.LayoutElementMatcher other);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-testing/build.gradle b/wear/protolayout/protolayout-testing/build.gradle
index 565226d..443c60b 100644
--- a/wear/protolayout/protolayout-testing/build.gradle
+++ b/wear/protolayout/protolayout-testing/build.gradle
@@ -31,16 +31,32 @@
 
 dependencies {
     api(libs.kotlinStdlib)
+    api(project(":wear:protolayout:protolayout"))
+    api(project(":wear:protolayout:protolayout-expression"))
     implementation("androidx.annotation:annotation:1.8.1")
+    implementation(project(":wear:protolayout:protolayout-proto"))
+    implementation(project(":wear:protolayout:protolayout-expression-pipeline"))
+
+    testImplementation(libs.junit)
+    testImplementation(libs.robolectric)
+    testImplementation(libs.testExtJunit)
+    testImplementation(libs.truth)
 }
 
 android {
+    defaultConfig {
+        minSdkVersion 26
+    }
     namespace "androidx.wear.protolayout.testing"
+
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
 }
 
 androidx {
     name = "androidx.wear.protolayout:protolayout-testing"
-    type = LibraryType.PUBLISHED_LIBRARY
+    type = LibraryType.PUBLISHED_TEST_LIBRARY
     inceptionYear = "2024"
     description = "Testing framework for protolayout element tree."
 }
diff --git a/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementAssertion.kt b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementAssertion.kt
new file mode 100644
index 0000000..f34070d
--- /dev/null
+++ b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementAssertion.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2024 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.protolayout.testing
+
+import androidx.wear.protolayout.LayoutElementBuilders
+import java.lang.AssertionError
+
+/**
+ * Represents a layout element that can be asserted on.
+ *
+ * <p>An instance of [LayoutElementAssertion] can be obtained from 'onElement' method on a
+ * [LayoutElementAssertionsProvider].
+ */
+public class LayoutElementAssertion
+internal constructor(
+    private val elementDescription: String,
+    internal val element: LayoutElementBuilders.LayoutElement?,
+) {
+    /** Asserts that the element was found in the element tree. */
+    public fun assertExists() {
+        if (element == null) {
+            throw AssertionError("Expected $elementDescription to exist, but it does not.")
+        }
+    }
+
+    /** Asserts that no element was found in the element tree. */
+    public fun assertDoesNotExist() {
+        if (element != null) {
+            throw AssertionError("Expected $elementDescription to not exist, but it does.")
+        }
+    }
+
+    /** Asserts that the provided [LayoutElementMatcher] is satisfied for this element. */
+    public fun assert(matcher: LayoutElementMatcher): LayoutElementAssertion {
+        assertExists()
+        if (!matcher.matches(element!!)) {
+            throw AssertionError(
+                "Expected $elementDescription to match '${matcher.description}'," +
+                    " but it does not."
+            )
+        }
+        return this
+    }
+}
diff --git a/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementAssertionsProvider.kt b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementAssertionsProvider.kt
new file mode 100644
index 0000000..4971419
--- /dev/null
+++ b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementAssertionsProvider.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 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.protolayout.testing
+
+import androidx.wear.protolayout.LayoutElementBuilders.Layout
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
+import androidx.wear.protolayout.LayoutElementBuilders.layoutElementFromProto
+
+/** Provides the main entry point into testing by exposing methods to find a layout element. */
+public class LayoutElementAssertionsProvider(layoutRoot: LayoutElement) {
+    private val root: LayoutElement =
+        layoutElementFromProto(layoutRoot.toLayoutElementProto(), null)
+
+    public constructor(layout: Layout) : this(layout.root!!)
+
+    /** Finds an element that matches the given condition. */
+    public fun onElement(matcher: LayoutElementMatcher): LayoutElementAssertion {
+        val elementDescription = "element matching '${matcher.description}'"
+        return LayoutElementAssertion(elementDescription, searchElement(root, matcher))
+    }
+
+    /**
+     * Finds the top level element of the element tree added to this
+     * [LayoutElementAssertionsProvider].
+     */
+    public fun onRoot(): LayoutElementAssertion = LayoutElementAssertion("root", root)
+
+    // TODO - b/374944199: add onAllElement which returns a LayoutElementAssertionCollection
+}
diff --git a/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementMatcher.kt b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementMatcher.kt
new file mode 100644
index 0000000..77aa0c9
--- /dev/null
+++ b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/LayoutElementMatcher.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2024 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.protolayout.testing
+
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
+
+/**
+ * Wrapper for element matcher lambdas that allows to build string explaining to the developer what
+ * conditions are being tested.
+ *
+ * @param description a string explaining to the developer what conditions were being tested.
+ * @param matcher a lambda performing the actual logic of matching on the layout element.
+ */
+public class LayoutElementMatcher(
+    internal val description: String,
+    private val matcher: (LayoutElement) -> Boolean
+) {
+    /** Returns whether the given element is matched by this matcher. */
+    internal fun matches(element: LayoutElement): Boolean = matcher(element)
+
+    /**
+     * Returns whether the given element is matched by both this and the other mather.
+     *
+     * @param other mather that should also match in addition to current matcher.
+     */
+    public infix fun and(other: LayoutElementMatcher): LayoutElementMatcher =
+        LayoutElementMatcher("($description) && (${other.description})") {
+            matcher(it) && other.matches(it)
+        }
+
+    /**
+     * Returns whether the given element is matched by this or the other mather.
+     *
+     * @param other mather that can be tested to match if the current matcher does not.
+     */
+    public infix fun or(other: LayoutElementMatcher): LayoutElementMatcher =
+        LayoutElementMatcher("($description) || (${other.description})") {
+            matcher(it) || other.matches(it)
+        }
+
+    /** Returns whether the given element does not match the matcher. */
+    public operator fun not(): LayoutElementMatcher =
+        LayoutElementMatcher("NOT ($description)") { !matcher(it) }
+}
diff --git a/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/helpers.kt b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/helpers.kt
new file mode 100644
index 0000000..de300bc
--- /dev/null
+++ b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/helpers.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024 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.protolayout.testing
+
+import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.Column
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
+import androidx.wear.protolayout.LayoutElementBuilders.Row
+
+internal val LayoutElement.children: List<LayoutElement>
+    get() =
+        when (this) {
+            is Box -> this.contents
+            is Row -> this.contents
+            is Column -> this.contents
+            // TODO b/372916396 - Dealing with Arc container and ArcLayoutElements
+            else -> emptyList<LayoutElement>()
+        }
+
+internal fun searchElement(root: LayoutElement?, matcher: LayoutElementMatcher): LayoutElement? {
+    if (root == null) return null
+    if (matcher.matches(root)) return root
+    return root.children.firstNotNullOfOrNull { searchElement(it, matcher) }
+}
diff --git a/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/package-info.java b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/package-info.java
index cef88a5..46afd06 100644
--- a/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/package-info.java
+++ b/wear/protolayout/protolayout-testing/src/main/java/androidx/wear/protolayout/testing/package-info.java
@@ -14,8 +14,4 @@
  * limitations under the License.
  */
 
-// TODO(b/371013214): Make protolayout-testing library public.
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 package androidx.wear.protolayout.testing;
-
-import androidx.annotation.RestrictTo;
diff --git a/wear/protolayout/protolayout-testing/src/test/java/androidx/wear/protolayout/testing/LayoutElementAssertionTest.kt b/wear/protolayout/protolayout-testing/src/test/java/androidx/wear/protolayout/testing/LayoutElementAssertionTest.kt
new file mode 100644
index 0000000..924796a
--- /dev/null
+++ b/wear/protolayout/protolayout-testing/src/test/java/androidx/wear/protolayout/testing/LayoutElementAssertionTest.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2024 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.protolayout.testing
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.Text
+import com.google.common.truth.ExpectFailure.assertThat
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(AndroidJUnit4::class)
+@DoNotInstrument
+class LayoutElementAssertionTest {
+
+    @Test
+    fun assertExists_success() {
+        val assertion = LayoutElementAssertion(ELEMENT_DESCRIPTION, Box.Builder().build())
+
+        assertion.assertExists() // no error
+    }
+
+    @Test
+    fun assertExists_error() {
+        val assertion = LayoutElementAssertion(ELEMENT_DESCRIPTION, null)
+
+        val assertionError = assertThrows(AssertionError::class.java) { assertion.assertExists() }
+
+        assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo("Expected $ELEMENT_DESCRIPTION to exist, but it does not.")
+    }
+
+    @Test
+    fun assertDoesNotExist_success() {
+        val assertion = LayoutElementAssertion(ELEMENT_DESCRIPTION, null)
+
+        assertion.assertDoesNotExist() // no error
+    }
+
+    @Test
+    fun assertDoesNotExist_error() {
+        val assertion = LayoutElementAssertion(ELEMENT_DESCRIPTION, Box.Builder().build())
+
+        val assertionError =
+            assertThrows(AssertionError::class.java) { assertion.assertDoesNotExist() }
+
+        assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo("Expected $ELEMENT_DESCRIPTION to not exist, but it does.")
+    }
+
+    @Test
+    fun assert_withMatcher_success() {
+        val assertion = LayoutElementAssertion(ELEMENT_DESCRIPTION, Box.Builder().build())
+        assertion.assert(LayoutElementMatcher("Element type is Box") { it is Box })
+    }
+
+    @Test
+    fun assert_withMatcher_error() {
+        val assertion = LayoutElementAssertion(ELEMENT_DESCRIPTION, Box.Builder().build())
+        val matcher = LayoutElementMatcher("Element type is Text") { it is Text }
+
+        val assertionError = assertThrows(AssertionError::class.java) { assertion.assert(matcher) }
+
+        assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo(
+                "Expected $ELEMENT_DESCRIPTION to match '${matcher.description}'," +
+                    " but it does not."
+            )
+    }
+
+    @Test
+    fun chainAssertions() {
+        val textContent = "testing text"
+        val assertion =
+            LayoutElementAssertion(ELEMENT_DESCRIPTION, Text.Builder().setText(textContent).build())
+        val typeMatcher = LayoutElementMatcher("Element type is Text") { it is Text }
+        val contentMatcher =
+            LayoutElementMatcher("Element text = '$textContent'") {
+                it is Text && it.text?.value == textContent
+            }
+
+        assertion.assert(typeMatcher).assert(contentMatcher)
+    }
+
+    @Test
+    fun chainAssertions_failureInFirst() {
+        val textContent = "testing text"
+        val assertion =
+            LayoutElementAssertion(ELEMENT_DESCRIPTION, Text.Builder().setText(textContent).build())
+        val firstMatcher = LayoutElementMatcher("Element type is Box") { it is Box }
+        val secondMatcher = LayoutElementMatcher("Element type is Text") { it is Text }
+
+        val assertionError =
+            assertThrows(AssertionError::class.java) {
+                assertion.assert(firstMatcher).assert(secondMatcher)
+            }
+
+        assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo(
+                "Expected $ELEMENT_DESCRIPTION to match " +
+                    "'${firstMatcher.description}', " +
+                    "but it does not."
+            )
+    }
+
+    @Test
+    fun chainAssertions_failureInSecond() {
+        val textContent = "testing text"
+        val assertion =
+            LayoutElementAssertion(ELEMENT_DESCRIPTION, Text.Builder().setText(textContent).build())
+        val firstMatcher = LayoutElementMatcher("Element type is Text") { it is Text }
+        val secondMatcher = LayoutElementMatcher("Element type is Box") { it is Box }
+
+        val assertionError =
+            assertThrows(AssertionError::class.java) {
+                assertion.assert(firstMatcher).assert(secondMatcher)
+            }
+
+        assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo(
+                "Expected $ELEMENT_DESCRIPTION to match " +
+                    "'${secondMatcher.description}', " +
+                    "but it does not."
+            )
+    }
+
+    companion object {
+        const val ELEMENT_DESCRIPTION = "testing element"
+    }
+}
diff --git a/wear/protolayout/protolayout-testing/src/test/java/androidx/wear/protolayout/testing/LayoutElementAssertionsProviderTest.kt b/wear/protolayout/protolayout-testing/src/test/java/androidx/wear/protolayout/testing/LayoutElementAssertionsProviderTest.kt
new file mode 100644
index 0000000..036ef7d
--- /dev/null
+++ b/wear/protolayout/protolayout-testing/src/test/java/androidx/wear/protolayout/testing/LayoutElementAssertionsProviderTest.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2024 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.protolayout.testing
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.Column
+import androidx.wear.protolayout.LayoutElementBuilders.Image
+import androidx.wear.protolayout.LayoutElementBuilders.Layout
+import androidx.wear.protolayout.LayoutElementBuilders.Row
+import androidx.wear.protolayout.LayoutElementBuilders.Text
+import com.google.common.truth.ExpectFailure
+import com.google.common.truth.Truth.assertThat
+import junit.framework.TestCase.assertTrue
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(AndroidJUnit4::class)
+@DoNotInstrument
+class LayoutElementAssertionsProviderTest {
+
+    @Test
+    fun primaryConstructor_onRoot() {
+        assertTrue(LayoutElementAssertionsProvider(TEST_LAYOUT.root!!).onRoot().element is Box)
+    }
+
+    @Test
+    fun secondaryConstructor_onRoot() {
+        assertTrue(LayoutElementAssertionsProvider(TEST_LAYOUT).onRoot().element is Box)
+    }
+
+    @Test
+    fun onRoot_description() {
+        val assertionError =
+            assertThrows(AssertionError::class.java) {
+                LayoutElementAssertionsProvider(TEST_LAYOUT).onRoot().assertDoesNotExist()
+            }
+
+        val rootDescription = "root"
+
+        ExpectFailure.assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo("Expected $rootDescription to not exist, but it does.")
+    }
+
+    @Test
+    fun onElement_isImage() {
+        val firstImageElement =
+            LayoutElementAssertionsProvider(TEST_LAYOUT).onElement(isImage).element as Image
+        assertThat(firstImageElement.resourceId!!.value).isEqualTo("image1")
+    }
+
+    @Test
+    fun onElement_isText() {
+        val firstTextElement =
+            LayoutElementAssertionsProvider(TEST_LAYOUT).onElement(isText).element as Text
+        assertThat(firstTextElement.text!!.value).isEqualTo("text1")
+    }
+
+    @Test
+    fun onElement_description() {
+        val assertionError =
+            assertThrows(AssertionError::class.java) {
+                LayoutElementAssertionsProvider(TEST_LAYOUT).onElement(isText).assertDoesNotExist()
+            }
+
+        val elementDescription = "element matching '${isText.description}'"
+
+        ExpectFailure.assertThat(assertionError)
+            .hasMessageThat()
+            .isEqualTo("Expected $elementDescription to not exist, but it does.")
+    }
+
+    companion object {
+        val isBox = LayoutElementMatcher("Element type is Box") { it is Box }
+        val isImage = LayoutElementMatcher("Element type is Image") { it is Image }
+        val isText = LayoutElementMatcher("Element type is Text") { it is Text }
+        val TEST_LAYOUT =
+            Layout.Builder()
+                .setRoot(
+                    Box.Builder()
+                        .addContent(
+                            Row.Builder()
+                                .addContent(Image.Builder().setResourceId("image1").build())
+                                .addContent(Image.Builder().setResourceId("image2").build())
+                                .build()
+                        )
+                        .addContent(
+                            Column.Builder()
+                                .addContent(Text.Builder().setText("text1").build())
+                                .addContent(Text.Builder().setText("text2").build())
+                                .build()
+                        )
+                        .build()
+                )
+                .build()
+    }
+}
diff --git a/wear/protolayout/protolayout/api/current.txt b/wear/protolayout/protolayout/api/current.txt
index 7ef6729..034cbf0 100644
--- a/wear/protolayout/protolayout/api/current.txt
+++ b/wear/protolayout/protolayout/api/current.txt
@@ -558,6 +558,42 @@
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp.Builder setValue(int);
   }
 
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public static final class LayoutElementBuilders.DashedArcLine implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint? getLayoutConstraintsForDynamicLength();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getLength();
+    method public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern? getLinePattern();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getThickness();
+  }
+
+  public static final class LayoutElementBuilders.DashedArcLine.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public LayoutElementBuilders.DashedArcLine.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setLayoutConstraintsForDynamicLength(androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setLength(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setLinePattern(androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public static final class LayoutElementBuilders.DashedLinePattern {
+    method public java.util.List<androidx.wear.protolayout.DimensionBuilders.DegreesProp!> getGapLocations();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getGapSize();
+  }
+
+  public static final class LayoutElementBuilders.DashedLinePattern.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public LayoutElementBuilders.DashedLinePattern.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern.Builder setGapInterval(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern.Builder setGapLocations(float...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern.Builder setGapSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
   @SuppressCompatibility @androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class LayoutElementBuilders.ExtensionLayoutElement implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
     method public String getExtensionId();
     method public androidx.wear.protolayout.DimensionBuilders.ExtensionDimension? getHeight();
diff --git a/wear/protolayout/protolayout/api/restricted_current.txt b/wear/protolayout/protolayout/api/restricted_current.txt
index 7ef6729..034cbf0 100644
--- a/wear/protolayout/protolayout/api/restricted_current.txt
+++ b/wear/protolayout/protolayout/api/restricted_current.txt
@@ -558,6 +558,42 @@
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp.Builder setValue(int);
   }
 
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public static final class LayoutElementBuilders.DashedArcLine implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint? getLayoutConstraintsForDynamicLength();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getLength();
+    method public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern? getLinePattern();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getThickness();
+  }
+
+  public static final class LayoutElementBuilders.DashedArcLine.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public LayoutElementBuilders.DashedArcLine.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setLayoutConstraintsForDynamicLength(androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setLength(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setLinePattern(androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine.Builder setThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public static final class LayoutElementBuilders.DashedLinePattern {
+    method public java.util.List<androidx.wear.protolayout.DimensionBuilders.DegreesProp!> getGapLocations();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getGapSize();
+  }
+
+  public static final class LayoutElementBuilders.DashedLinePattern.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public LayoutElementBuilders.DashedLinePattern.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern.Builder setGapInterval(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern.Builder setGapLocations(float...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=500) public androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern.Builder setGapSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
   @SuppressCompatibility @androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class LayoutElementBuilders.ExtensionLayoutElement implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
     method public String getExtensionId();
     method public androidx.wear.protolayout.DimensionBuilders.ExtensionDimension? getHeight();
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
index 7c4af90..8fbf8f0 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
@@ -16,6 +16,9 @@
 
 package androidx.wear.protolayout;
 
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.degrees;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
 import static androidx.wear.protolayout.DimensionBuilders.sp;
 import static androidx.wear.protolayout.expression.Preconditions.checkNotNull;
 
@@ -5170,6 +5173,457 @@
         }
     }
 
+    /**
+     * A dashed arc line that can be placed in an {@link Arc} container. It is an arc line made up
+     * of arc line segments separated by gaps.
+     */
+    @RequiresSchemaVersion(major = 1, minor = 500)
+    public static final class DashedArcLine implements ArcLayoutElement {
+        private final LayoutElementProto.DashedArcLine mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        DashedArcLine(LayoutElementProto.DashedArcLine impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the length of this line in degrees, including gaps.
+         *
+         * <p>When using a dynamic value, make sure to specify the bounding constraints for the
+         * affected layout element through {@code setLayoutConstraintsForDynamicLength
+         * (AngularLayoutConstraint)}, otherwise {@code build()} fails.
+         */
+        @Nullable
+        public DegreesProp getLength() {
+            if (mImpl.hasLength()) {
+                return DegreesProp.fromProto(mImpl.getLength());
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets the thickness of this line. */
+        @Dimension(unit = DP)
+        public float getThickness() {
+            if (mImpl.hasThickness()) {
+                return DpProp.fromProto(mImpl.getThickness()).getValue();
+            } else {
+                return 0;
+            }
+        }
+
+        /** Gets the color of this line. */
+        @Nullable
+        public ColorProp getColor() {
+            if (mImpl.hasColor()) {
+                return ColorProp.fromProto(mImpl.getColor());
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets {@link androidx.wear.protolayout.ModifiersBuilders.Modifiers} for this element. */
+        @Nullable
+        public ArcModifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return ArcModifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets the direction in which this line is drawn. */
+        @Nullable
+        public ArcDirectionProp getArcDirection() {
+            if (mImpl.hasArcDirection()) {
+                return ArcDirectionProp.fromProto(mImpl.getArcDirection());
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets the dashed line pattern which describes how the arc line is segmented by gaps. */
+        @Nullable
+        public DashedLinePattern getLinePattern() {
+            if (mImpl.hasLinePattern()) {
+                return DashedLinePattern.fromProto(mImpl.getLinePattern());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the bounding constraints for the layout affected by the dynamic value from {@link
+         * #getLength()}.
+         */
+        @Nullable
+        public AngularLayoutConstraint getLayoutConstraintsForDynamicLength() {
+            if (mImpl.hasLength()) {
+                return AngularLayoutConstraint.fromProto(mImpl.getLength());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static DashedArcLine fromProto(
+                @NonNull LayoutElementProto.DashedArcLine proto,
+                @Nullable Fingerprint fingerprint) {
+            return new DashedArcLine(proto, fingerprint);
+        }
+
+        @NonNull
+        static DashedArcLine fromProto(@NonNull LayoutElementProto.DashedArcLine proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @NonNull
+        LayoutElementProto.DashedArcLine toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
+            return LayoutElementProto.ArcLayoutElement.newBuilder().setDashedLine(mImpl).build();
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "DashedArcLine{"
+                    + "length="
+                    + getLength()
+                    + ", thickness="
+                    + getThickness()
+                    + ", color="
+                    + getColor()
+                    + ", modifiers="
+                    + getModifiers()
+                    + ", arcDirection="
+                    + getArcDirection()
+                    + ", linePattern="
+                    + getLinePattern()
+                    + "}";
+        }
+
+        /** Builder for {@link DashedArcLine}. */
+        @SuppressWarnings("HiddenSuperclass")
+        public static final class Builder implements ArcLayoutElement.Builder {
+            private final LayoutElementProto.DashedArcLine.Builder mImpl =
+                    LayoutElementProto.DashedArcLine.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1152963772);
+
+            /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            public Builder() {}
+
+            /**
+             * Sets the length of this line, in degrees. If not defined, defaults to 0.
+             *
+             * <p>When using a dynamic value, make sure to specify the bounding constraints for the
+             * affected layout element through {@code setLayoutConstraintsForDynamicLength
+             * (AngularLayoutConstraint)} otherwise {@code build()} fails.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setLength(@NonNull DegreesProp length) {
+                mImpl.mergeLength(length.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(length.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the thickness of this line. If not defined, defaults to 0.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setThickness(@Dimension(unit = DP) float thickness) {
+                DpProp thicknessProp = dp(thickness);
+                mImpl.setThickness(thicknessProp.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(thicknessProp.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the color of this line.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setColor(@NonNull ColorProp color) {
+                mImpl.setColor(color.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(color.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets {@link androidx.wear.protolayout.ModifiersBuilders.Modifiers} for this element.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setModifiers(@NonNull ArcModifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the direction in which this line is drawn. If not set, defaults to
+             * ARC_DIRECTION_CLOCKWISE.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setArcDirection(@NonNull ArcDirectionProp arcDirection) {
+                mImpl.setArcDirection(arcDirection.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(arcDirection.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the direction in which this line is drawn. If not set, defaults to
+             * ARC_DIRECTION_CLOCKWISE.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setArcDirection(@ArcDirection int arcDirection) {
+                return setArcDirection(
+                        new ArcDirectionProp.Builder().setValue(arcDirection).build());
+            }
+
+            /**
+             * Sets the dashed line pattern which describes how the arc line is segmented by gaps.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setLinePattern(@NonNull DashedLinePattern linePattern) {
+                mImpl.setLinePattern(linePattern.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        6, checkNotNull(linePattern.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the bounding constraints for the layout affected by the dynamic value from
+             * {@link #setLength(DegreesProp)}.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setLayoutConstraintsForDynamicLength(
+                    @NonNull AngularLayoutConstraint angularLayoutConstraint) {
+                mImpl.mergeLength(angularLayoutConstraint.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1,
+                        checkNotNull(angularLayoutConstraint.getFingerprint())
+                                .aggregateValueAsInt());
+                return this;
+            }
+
+            /** Builds an instance with the values accumulated in this Builder. */
+            @SuppressLint("ProtoLayoutMinSchema")
+            @Override
+            @NonNull
+            public DashedArcLine build() {
+                DimensionProto.DegreesProp length = mImpl.getLength();
+                if (length.hasDynamicValue() && !length.hasValueForLayout()) {
+                    throw new IllegalStateException(
+                            "length with dynamic value requires "
+                                    + "layoutConstraintsForDynamicLength to be present.");
+                }
+
+                return new DashedArcLine(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** A dashed line pattern which describes how the dashed arc line is segmented by gaps. */
+    @RequiresSchemaVersion(major = 1, minor = 500)
+    public static final class DashedLinePattern {
+        private final LayoutElementProto.DashedLinePattern mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        DashedLinePattern(
+                LayoutElementProto.DashedLinePattern impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the size in dp of the gap between the arc line segments. */
+        @Nullable
+        public DpProp getGapSize() {
+            if (mImpl.hasGapSize()) {
+                return DpProp.fromProto(mImpl.getGapSize());
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets the list of each gap's center location in degrees. */
+        @NonNull
+        public List<DegreesProp> getGapLocations() {
+            List<DegreesProp> list = new ArrayList<>();
+            for (DimensionProto.DegreesProp item : mImpl.getGapLocationsList()) {
+                list.add(DegreesProp.fromProto(item));
+            }
+            return Collections.unmodifiableList(list);
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static DashedLinePattern fromProto(
+                @NonNull LayoutElementProto.DashedLinePattern proto,
+                @Nullable Fingerprint fingerprint) {
+            return new DashedLinePattern(proto, fingerprint);
+        }
+
+        @NonNull
+        static DashedLinePattern fromProto(@NonNull LayoutElementProto.DashedLinePattern proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.DashedLinePattern toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "DashedLinePattern{"
+                    + "gapSize="
+                    + getGapSize()
+                    + ", gapLocations="
+                    + getGapLocations()
+                    + "}";
+        }
+
+        /** Builder for {@link DashedLinePattern} */
+        public static final class Builder {
+            private final LayoutElementProto.DashedLinePattern.Builder mImpl =
+                    LayoutElementProto.DashedLinePattern.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1050989205);
+
+            /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            public Builder() {}
+
+            /**
+             * Sets the size in dp of the gap between the segments. If not defined, defaults to 0.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setGapSize(@Dimension(unit = DP) float gapSizeInDp) {
+                DpProp gapSizeProp = dp(gapSizeInDp);
+                mImpl.setGapSize(gapSizeProp.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(gapSizeProp.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Adds one item to the list of each gap's center location in degrees.
+             *
+             * <p>Note that this field only supports static values.
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            private Builder addGapLocation(@NonNull DegreesProp gapLocation) {
+                if (gapLocation.getDynamicValue() != null) {
+                    throw new IllegalArgumentException(
+                            "DashedLinePattern.Builder.addGapLocation doesn't support dynamic "
+                                    + "values.");
+                }
+                mImpl.addGapLocations(gapLocation.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(gapLocation.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the list of each gap's center location in degrees.
+             *
+             * <p>The interval between any two locations could not be shorter than thickness plus
+             * gap size.
+             *
+             * <p>Note that calling this method will invalidate the previous call of {@link
+             * #setGapInterval}
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            public Builder setGapLocations(@NonNull float... gapLocationsInDegrees) {
+                mImpl.clearGapLocations();
+
+                for (float gapLocation: gapLocationsInDegrees) {
+                    addGapLocation(degrees(gapLocation));
+                }
+
+                return this;
+            }
+
+            /**
+             * Sets the interval length in degrees between two consecutive gap center locations. The
+             * arc line will have arc line segments with equal length.
+             *
+             * <p>The interval could not be shorter than thickness plus gap size.
+             *
+             * <p>Note that calling this method will remove all the gap locations set previously
+             * with {@link #setGapLocations}
+             */
+            @RequiresSchemaVersion(major = 1, minor = 500)
+            @NonNull
+            @SuppressLint("MissingGetterMatchingBuilder")
+            public Builder setGapInterval(float gapIntervalInDegrees) {
+                mImpl.clearGapLocations();
+
+                float gapLocation = gapIntervalInDegrees;
+                while (gapLocation <= 360F) {
+                    addGapLocation(degrees(gapLocation));
+                    gapLocation += gapIntervalInDegrees;
+                }
+
+                return this;
+            }
+
+            private static final int GAP_COUNTS_LIMIT = 100;
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public DashedLinePattern build() {
+                if (mImpl.getGapLocationsList().size() > GAP_COUNTS_LIMIT) {
+                    throw new IllegalArgumentException(
+                            "Number of gaps can't be larger than " + GAP_COUNTS_LIMIT + ".");
+                }
+                return new DashedLinePattern(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+
     /** A simple spacer used to provide padding between adjacent elements in an {@link Arc}. */
     @RequiresSchemaVersion(major = 1, minor = 0)
     public static final class ArcSpacer implements ArcLayoutElement {
@@ -5871,6 +6325,9 @@
         if (proto.hasAdapter()) {
             return ArcAdapter.fromProto(proto.getAdapter(), fingerprint);
         }
+        if (proto.hasDashedLine()) {
+            return DashedArcLine.fromProto(proto.getDashedLine(), fingerprint);
+        }
         throw new IllegalStateException("Proto was not a recognised instance of ArcLayoutElement");
     }
 
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/LayoutElementBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/LayoutElementBuildersTest.java
index 1653411..5605c8b 100644
--- a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/LayoutElementBuildersTest.java
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/LayoutElementBuildersTest.java
@@ -21,6 +21,8 @@
 import static androidx.wear.protolayout.DimensionBuilders.expand;
 import static androidx.wear.protolayout.DimensionBuilders.sp;
 import static androidx.wear.protolayout.DimensionBuilders.weight;
+import static androidx.wear.protolayout.LayoutElementBuilders.ARC_DIRECTION_COUNTER_CLOCKWISE;
+import static androidx.wear.protolayout.LayoutElementBuilders.ARC_DIRECTION_NORMAL;
 import static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.ROBOTO_FLEX_FONT;
 import static androidx.wear.protolayout.LayoutElementBuilders.TABULAR_OPTION_TAG;
 import static androidx.wear.protolayout.LayoutElementBuilders.WEIGHT_AXIS_TAG;
@@ -35,6 +37,9 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.wear.protolayout.expression.AppDataKey;
 import androidx.wear.protolayout.expression.DynamicBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine;
+import androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern;
+import androidx.wear.protolayout.proto.ColorProto;
 import androidx.wear.protolayout.proto.DimensionProto;
 import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.protolayout.proto.TypesProto;
@@ -467,7 +472,7 @@
 
     @Test
     public void testArcs_withSetDirection_correctlySetsValues() {
-        int arcLineDirection = LayoutElementBuilders.ARC_DIRECTION_COUNTER_CLOCKWISE;
+        int arcLineDirection = ARC_DIRECTION_COUNTER_CLOCKWISE;
         int arcTextDirection = LayoutElementBuilders.ARC_DIRECTION_NORMAL;
         int arcDirection = LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE;
 
@@ -712,4 +717,113 @@
         assertThat(fontStyleProto.getPreferredFontFamilies(0)).isEqualTo(expectedFontFamily);
         assertThat(fontStyleProto.getPreferredFontFamilies(1)).isEqualTo(fallbackFontFamily);
     }
+
+    @Test
+    public void dashedArcLine_length() {
+        DashedArcLine dashedArcLine =
+                new DashedArcLine.Builder()
+                        .setLength(DEGREES_PROP)
+                        .setLayoutConstraintsForDynamicLength(DEGREES_PROP_CONSTRAINT)
+                        .build();
+
+        DimensionProto.DegreesProp lengthProto = dashedArcLine.toProto().getLength();
+
+        assertThat(lengthProto.getValue()).isEqualTo(DEGREES_PROP.getValue());
+        assertThat(lengthProto.getDynamicValue().getStateSource().getSourceKey())
+                .isEqualTo(STATE_KEY);
+        assertThat(lengthProto.getValueForLayout()).isEqualTo(DEGREES_PROP_CONSTRAINT.getValue());
+        assertThat(lengthProto.getAngularAlignmentForLayoutValue())
+                .isEqualTo(DEGREES_PROP_CONSTRAINT.getAngularAlignment());
+    }
+
+    @Test
+    public void dashedArcLine_length_withoutLayoutConstraint_throws() {
+        assertThrows(
+                IllegalStateException.class,
+                () -> new DashedArcLine.Builder().setLength(DEGREES_PROP).build());
+    }
+
+    @Test
+    public void dashedArcLine_thickness() {
+        float thickness = 5F;
+        DashedArcLine dashedArcLine =
+                new DashedArcLine.Builder()
+                        .setThickness(thickness)
+                        .build();
+
+        assertThat(dashedArcLine.toProto().getThickness().getValue())
+                .isEqualTo(thickness);
+    }
+
+    @Test
+    public void dashedArcLine_color() {
+        String stateKey = "color-key";
+        ColorBuilders.ColorProp color =
+                new ColorBuilders.ColorProp.Builder(Color.BLUE)
+                        .setDynamicValue(DynamicBuilders.DynamicColor.from(
+                                new AppDataKey<>(stateKey)
+                        )).build();
+        DashedArcLine dashedArcLine =
+                new DashedArcLine.Builder()
+                        .setColor(color)
+                        .build();
+
+        ColorProto.ColorProp colorProto = dashedArcLine.toProto().getColor();
+        assertThat(colorProto.getArgb()).isEqualTo(Color.BLUE);
+        assertThat(colorProto.getDynamicValue().getStateSource().getSourceKey())
+                .isEqualTo(stateKey);
+    }
+
+    @Test
+    public void dashedArcLine_arcDirection() {
+        DashedArcLine dashedArcLine1 =
+                new DashedArcLine.Builder().build();
+        DashedArcLine dashedArcLine2 =
+                new DashedArcLine.Builder()
+                        .setArcDirection(ARC_DIRECTION_COUNTER_CLOCKWISE)
+                        .build();
+
+        assertThat(dashedArcLine1.toProto().getArcDirection().getValue().getNumber())
+                .isEqualTo(ARC_DIRECTION_NORMAL);
+        assertThat(dashedArcLine2.toProto().getArcDirection().getValue().getNumber())
+                .isEqualTo(ARC_DIRECTION_COUNTER_CLOCKWISE);
+    }
+
+    @Test
+    public void dashedArcLine_brushWithEqualSegments() {
+        DashedArcLine dashedArcLine =
+                new DashedArcLine.Builder()
+                        .setLinePattern(
+                                new DashedLinePattern.Builder()
+                                        .setGapSize(4.5F)
+                                        .setGapInterval(111)
+                                        .build())
+                        .build();
+
+        LayoutElementProto.DashedLinePattern brush = dashedArcLine.getLinePattern().toProto();
+        assertThat(brush.getGapSize().getValue()).isEqualTo(4.5F);
+        List<DimensionProto.DegreesProp> gapLocations =brush.getGapLocationsList();
+        assertThat(gapLocations.get(0).getValue()).isEqualTo(111F);
+        assertThat(gapLocations.get(1).getValue()).isEqualTo(222F);
+        assertThat(gapLocations.get(2).getValue()).isEqualTo(333F);
+    }
+
+    @Test
+    public void dashedArcLine_brushWithNonEqualSegments() {
+        DashedArcLine dashedArcLine =
+                new DashedArcLine.Builder()
+                        .setLinePattern(
+                                new DashedLinePattern.Builder()
+                                        .setGapSize(4.5F)
+                                        .setGapLocations(66F, 111F, 321F, 212F).build())
+                        .build();
+
+        LayoutElementProto.DashedLinePattern brush = dashedArcLine.getLinePattern().toProto();
+        assertThat(brush.getGapSize().getValue()).isEqualTo(4.5F);
+        List<DimensionProto.DegreesProp> gapLocations =brush.getGapLocationsList();
+        assertThat(gapLocations.get(0).getValue()).isEqualTo(66F);
+        assertThat(gapLocations.get(1).getValue()).isEqualTo(111F);
+        assertThat(gapLocations.get(2).getValue()).isEqualTo(321F);
+        assertThat(gapLocations.get(3).getValue()).isEqualTo(212F);
+    }
 }