Merge "Fixed failing integration test for FastScrollViewIntegrationTest" into androidx-main
diff --git a/benchmark/benchmark-common/build.gradle b/benchmark/benchmark-common/build.gradle
index 6646ae9..70622c4 100644
--- a/benchmark/benchmark-common/build.gradle
+++ b/benchmark/benchmark-common/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.AndroidXConfig
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -94,6 +96,7 @@
     inceptionYear = "2018"
     description = "Android Benchmark - Common"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 tasks.withType(KotlinCompile).configureEach {
diff --git a/benchmark/benchmark-junit4/build.gradle b/benchmark/benchmark-junit4/build.gradle
index 4a0d751..aafa2a8 100644
--- a/benchmark/benchmark-junit4/build.gradle
+++ b/benchmark/benchmark-junit4/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
@@ -63,6 +65,7 @@
     inceptionYear = "2019"
     description = "Android Benchmark - JUnit4"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 tasks.withType(KotlinCompile).configureEach {
diff --git a/benchmark/benchmark-macro-junit4/build.gradle b/benchmark/benchmark-macro-junit4/build.gradle
index 5b0de69..4f9ef1f 100644
--- a/benchmark/benchmark-macro-junit4/build.gradle
+++ b/benchmark/benchmark-macro-junit4/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
@@ -75,4 +77,5 @@
     inceptionYear = "2020"
     description = "Android Benchmark - Macrobenchmark JUnit4"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/benchmark/benchmark-macro/build.gradle b/benchmark/benchmark-macro/build.gradle
index 23786dd..3ffb560 100644
--- a/benchmark/benchmark-macro/build.gradle
+++ b/benchmark/benchmark-macro/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.AndroidXConfig
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -176,4 +178,5 @@
         targetAppProject = project(":benchmark:integration-tests:macrobenchmark-target")
         targetAppVariant = "release"
     }
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
index aea92fb..e178e58 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
@@ -143,7 +143,7 @@
  * If true, enable the ArrayNullnessMigration lint check to transition to type-use nullness
  * annotations. Defaults to false.
  */
-const val MIGRATE_ARRAY_ANNOTATIONS = "androidx.migrateArrayAnnotations"
+const val USE_JSPECIFY_ANNOTATIONS = "androidx.useJSpecifyAnnotations"
 
 /** If true, yarn dependencies are fetched from an offline mirror */
 const val YARN_OFFLINE_MODE = "androidx.yarnOfflineMode"
@@ -186,7 +186,7 @@
         FilteredAnchorTask.PROP_TASK_NAME,
         FilteredAnchorTask.PROP_PATH_PREFIX,
         INCLUDE_OPTIONAL_PROJECTS,
-        MIGRATE_ARRAY_ANNOTATIONS,
+        USE_JSPECIFY_ANNOTATIONS,
         YARN_OFFLINE_MODE,
         FORCE_KOTLIN_2_0_TARGET,
         FORCE_BENCHMARK_AOT_COMPILATION,
@@ -289,10 +289,10 @@
     findBooleanProperty(ALLOW_CUSTOM_COMPILE_SDK) ?: true
 
 /**
- * Whether to enable the ArrayNullnessMigration lint check for moving nullness annotations on arrays
- * when switching a project to type-use nullness annotations.
+ * Whether to enable the JSpecifyNullnessMigration lint check for moving nullness annotations when
+ * switching a project to the JSpecify type-use nullness annotations.
  */
-fun Project.migrateArrayAnnotations() = findBooleanProperty(MIGRATE_ARRAY_ANNOTATIONS) ?: false
+fun Project.useJSpecifyAnnotations() = findBooleanProperty(USE_JSPECIFY_ANNOTATIONS) ?: false
 
 fun Project.findBooleanProperty(propName: String) = booleanPropertyProvider(propName).get()
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index f875c2f..cd8fc46 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -417,6 +417,16 @@
             evaluatedProject.kotlinExtensionOrNull?.let { kotlinExtension ->
                 kotlinExtension.coreLibrariesVersion = kotlinVersionStringProvider.get()
             }
+            if (evaluatedProject.androidXExtension.shouldPublish()) {
+                tasks.register(
+                    CheckKotlinApiTargetTask.TASK_NAME,
+                    CheckKotlinApiTargetTask::class.java
+                ) {
+                    it.kotlinTarget.set(kotlinVersionProvider)
+                    it.outputFile.set(layout.buildDirectory.file("kotlinApiTargetCheckReport.txt"))
+                }
+                addToBuildOnServer(CheckKotlinApiTargetTask.TASK_NAME)
+            }
         }
 
         // Resolve classpath conflicts caused by kotlin-stdlib-jdk7 and -jdk8 artifacts by amending
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt
new file mode 100644
index 0000000..62dbdd0
--- /dev/null
+++ b/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.build
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.work.DisableCachingByDefault
+import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
+
+/** Check if the kotlin-stdlib transitive dependencies are the same as the project specified one. */
+@DisableCachingByDefault(because = "not worth caching")
+abstract class CheckKotlinApiTargetTask : DefaultTask() {
+
+    @get:Input abstract val kotlinTarget: Property<KotlinVersion>
+
+    @get:Internal val projectPath: String = project.path
+
+    @get:Input
+    val allDependencies: List<Pair<String, String>> =
+        project.configurations
+            .filter {
+                it.isCanBeResolved &&
+                    !it.name.lowercase().contains("test") &&
+                    !it.name.lowercase().contains("metadata") &&
+                    !it.name.endsWith("CInterop")
+            }
+            .flatMap { config ->
+                config.resolvedConfiguration.firstLevelModuleDependencies.map {
+                    "${it.moduleName}:${it.moduleVersion}" to config.name
+                }
+            }
+
+    @get:OutputFile abstract val outputFile: RegularFileProperty
+
+    @TaskAction
+    fun check() {
+        val incompatibleConfigurations =
+            allDependencies
+                .asSequence()
+                .filter { it.first.startsWith("kotlin-stdlib:") }
+                .map { it.first.substringAfter(":") to it.second }
+                .map { KotlinVersion.fromVersion(it.first.substringBeforeLast('.')) to it.second }
+                .filter { it.first != kotlinTarget.get() }
+                .map { it.second }
+                .toList()
+
+        val outputFile = outputFile.get().asFile
+        outputFile.parentFile.mkdirs()
+
+        if (incompatibleConfigurations.isNotEmpty()) {
+            val errorMessage =
+                incompatibleConfigurations.joinToString(
+                    prefix =
+                        "The project's kotlin-stdlib target is ${kotlinTarget.get()} but these " +
+                            "configurations are pulling in different versions of kotlin-stdlib: ",
+                    postfix =
+                        "\nRun ./gradlew $projectPath:dependencies to see which dependency is " +
+                            "pulling in the incompatible kotlin-stdlib"
+                )
+            outputFile.writeText("FAILURE: $errorMessage")
+            throw IllegalStateException(errorMessage)
+        }
+    }
+
+    companion object {
+        const val TASK_NAME = "checkKotlinApiTarget"
+    }
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/Ktfmt.kt b/buildSrc/private/src/main/kotlin/androidx/build/Ktfmt.kt
index 1b01fa2..202a030 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/Ktfmt.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/Ktfmt.kt
@@ -19,21 +19,20 @@
 import androidx.build.logging.TERMINAL_RED
 import androidx.build.logging.TERMINAL_RESET
 import androidx.build.uptodatedness.cacheEvenIfNoOutputs
-import com.facebook.ktfmt.format.Formatter
-import com.facebook.ktfmt.format.Formatter.format
+import java.io.ByteArrayOutputStream
 import java.io.File
 import java.nio.file.Paths
 import javax.inject.Inject
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.async
-import kotlinx.coroutines.awaitAll
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.runBlocking
 import org.gradle.api.DefaultTask
 import org.gradle.api.Project
+import org.gradle.api.attributes.java.TargetJvmEnvironment
+import org.gradle.api.attributes.java.TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.FileCollection
 import org.gradle.api.file.FileTree
 import org.gradle.api.model.ObjectFactory
 import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.Classpath
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputFiles
 import org.gradle.api.tasks.Internal
@@ -43,21 +42,19 @@
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.options.Option
-import org.intellij.lang.annotations.Language
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import org.gradle.kotlin.dsl.named
+import org.gradle.process.ExecOperations
 
 fun Project.configureKtfmt() {
-    tasks.register("ktFormat", KtfmtFormatTask::class.java)
+    val ktfmtClasspath = getKtfmtConfiguration()
+    tasks.register("ktFormat", KtfmtFormatTask::class.java) { task ->
+        task.ktfmtClasspath.from(ktfmtClasspath)
+    }
 
     val ktCheckTask =
         tasks.register("ktCheck", KtfmtCheckTask::class.java) { task ->
+            task.ktfmtClasspath.from(ktfmtClasspath)
             task.cacheEvenIfNoOutputs()
-            // Workaround for https://github.com/gradle/gradle/issues/29205
-            // Our ktfmt tasks declare "src" as an input, while our KotlinCompile tasks use
-            // something like src/main/java as an input
-            // Currently Gradle can sometimes get confused when loading a parent and child directory
-            // at the same time, so we ask Gradle to avoid running both tasks in parallel
-            task.mustRunAfter(project.tasks.withType(KotlinCompile::class.java))
         }
 
     // afterEvaluate because Gradle's default "check" task doesn't exist yet
@@ -78,11 +75,27 @@
     )
 
 private val ExcludedDirectoryGlobs = ExcludedDirectories.map { "**/$it/**/*.kt" }
+private const val MainClass = "com.facebook.ktfmt.cli.Main"
 private const val InputDir = "src"
 private const val IncludedFiles = "**/*.kt"
 
+private fun Project.getKtfmtConfiguration(): FileCollection {
+    val conf = configurations.detachedConfiguration(dependencies.create(getLibraryByName("ktfmt")))
+    conf.attributes {
+        it.attribute(
+            TARGET_JVM_ENVIRONMENT_ATTRIBUTE,
+            project.objects.named(TargetJvmEnvironment.STANDARD_JVM)
+        )
+    }
+    return files(conf)
+}
+
 @CacheableTask
 abstract class BaseKtfmtTask : DefaultTask() {
+    @get:Inject abstract val execOperations: ExecOperations
+
+    @get:Classpath abstract val ktfmtClasspath: ConfigurableFileCollection
+
     @get:Inject abstract val objects: ObjectFactory
 
     @get:Internal val projectPath: String = project.path
@@ -114,54 +127,39 @@
 
     protected fun runKtfmt(format: Boolean) {
         if (getInputFiles().files.isEmpty()) return
-        runBlocking(Dispatchers.IO) {
-            val result = processInputFiles()
-            val incorrectlyFormatted = result.filter { !it.isCorrectlyFormatted }
-            if (incorrectlyFormatted.isNotEmpty()) {
-                if (format) {
-                    incorrectlyFormatted.forEach { it.input.writeText(it.formattedCode) }
-                } else {
-                    error(
-                        "Found ${incorrectlyFormatted.size} files that are not correctly " +
-                            "formatted:\n" +
-                            incorrectlyFormatted.map { it.input }.joinToString("\n") +
-                            """
-
-                ********************************************************************************
-                You can attempt to automatically fix these issues with:
-                ./gradlew $projectPath:ktFormat
-                ********************************************************************************
-                """
-                                .trimIndent()
-                    )
-                }
-            }
+        val outputStream = ByteArrayOutputStream()
+        execOperations.javaexec { javaExecSpec ->
+            javaExecSpec.standardOutput = outputStream
+            javaExecSpec.mainClass.set(MainClass)
+            javaExecSpec.classpath = ktfmtClasspath
+            javaExecSpec.args = getArgsList(format = format)
+            javaExecSpec.jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
+            overrideDirectory?.let { javaExecSpec.workingDir = it }
+        }
+        val output = outputStream.toString()
+        if (output.isNotEmpty()) {
+            processOutput(output)
+        }
+        if (output.isNotEmpty()) {
+            error(processOutput(output))
         }
     }
 
-    /** Run ktfmt on all the files in [getInputFiles] in parallel. */
-    private suspend fun processInputFiles(): List<KtfmtResult> {
-        return coroutineScope { getInputFiles().files.map { async { processFile(it) } }.awaitAll() }
-    }
+    open fun processOutput(output: String): String =
+        """
+        Failed check for the following files:
+        $output
+    """
+            .trimIndent()
 
-    /** Run ktfmt on the [input] file. */
-    private fun processFile(input: File): KtfmtResult {
-        val originCode = input.readText()
-        val formattedCode = format(Formatter.KOTLINLANG_FORMAT, originCode)
-        return KtfmtResult(
-            input = input,
-            isCorrectlyFormatted = originCode == formattedCode,
-            formattedCode = formattedCode
-        )
+    private fun getArgsList(format: Boolean): List<String> {
+        val arguments = mutableListOf("--kotlinlang-style")
+        if (!format) arguments.add("--dry-run")
+        arguments.addAll(getInputFiles().files.map { it.absolutePath })
+        return arguments
     }
 }
 
-internal data class KtfmtResult(
-    val input: File,
-    val isCorrectlyFormatted: Boolean,
-    @Language("kotlin") val formattedCode: String,
-)
-
 @CacheableTask
 abstract class KtfmtFormatTask : BaseKtfmtTask() {
     init {
@@ -189,6 +187,18 @@
     fun runCheck() {
         runKtfmt(format = false)
     }
+
+    override fun processOutput(output: String): String =
+        """
+                Failed check for the following files:
+                $output
+
+                ********************************************************************************
+                ${TERMINAL_RED}You can automatically fix these issues with:
+                ./gradlew $projectPath:ktFormat$TERMINAL_RESET
+                ********************************************************************************
+            """
+            .trimIndent()
 }
 
 @CacheableTask
@@ -243,33 +253,35 @@
 
     @TaskAction
     fun runCheck() {
-        try {
-            runKtfmt(format = format)
-        } catch (e: IllegalStateException) {
-            val kotlinFiles =
-                files.filter { file ->
-                    val isKotlinFile = file.endsWith(".kt") || file.endsWith(".ktx")
-                    val inExcludedDir =
-                        Paths.get(file).any { subPath ->
-                            ExcludedDirectories.contains(subPath.toString())
-                        }
+        runKtfmt(format = format)
+    }
 
-                    isKotlinFile && !inExcludedDir
-                }
-            error(
-                """
+    override fun processOutput(output: String): String {
+        val kotlinFiles =
+            files.filter { file ->
+                val isKotlinFile = file.endsWith(".kt") || file.endsWith(".ktx")
+                val inExcludedDir =
+                    Paths.get(file).any { subPath ->
+                        ExcludedDirectories.contains(subPath.toString())
+                    }
 
-                ********************************************************************************
-                ${TERMINAL_RED}You can attempt to automatically fix these issues with:
-                ./gradlew :ktCheckFile --format ${kotlinFiles.joinToString(separator = " "){ "--file $it" }}$TERMINAL_RESET
-                ********************************************************************************
-                """
-                    .trimIndent()
-            )
-        }
+                isKotlinFile && !inExcludedDir
+            }
+        return """
+            Failed check for the following files:
+            $output
+
+            ********************************************************************************
+            ${TERMINAL_RED}You can attempt to automatically fix these issues with:
+            ./gradlew :ktCheckFile --format ${kotlinFiles.joinToString(separator = " "){ "--file $it" }}$TERMINAL_RESET
+            ********************************************************************************
+            """
+            .trimIndent()
     }
 }
 
 fun Project.configureKtfmtCheckFile() {
-    tasks.register("ktCheckFile", KtfmtCheckFileTask::class.java)
+    tasks.register("ktCheckFile", KtfmtCheckFileTask::class.java) { task ->
+        task.ktfmtClasspath.from(getKtfmtConfiguration())
+    }
 }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt
index 563931b..25c421d 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -341,10 +341,10 @@
             disable.add("IllegalExperimentalApiUsage")
         }
 
-        // Only allow the ArrayMigration check to be run when opted-in, since this is meant to be
-        // run once per project when switching to type-use nullness annotations.
-        if (!project.migrateArrayAnnotations()) {
-            disable.add("ArrayMigration")
+        // Only allow the JSpecifyNullness check to be run when opted-in, while migrating projects
+        // to use JSpecify annotations.
+        if (!project.useJSpecifyAnnotations()) {
+            disable.add("JSpecifyNullness")
         }
 
         fatal.add("UastImplementation") // go/hide-uast-impl
diff --git a/buildSrc/shared-dependencies.gradle b/buildSrc/shared-dependencies.gradle
index 356e5ef..bc37d9f 100644
--- a/buildSrc/shared-dependencies.gradle
+++ b/buildSrc/shared-dependencies.gradle
@@ -39,8 +39,6 @@
     }
     implementation(libs.xerces)
 
-    implementation(libs.ktfmt)
-    implementation(libs.kotlinCoroutinesCore)
     implementation(libs.shadow) // used by BundleInsideHelper.kt
     api(libs.apacheAnt) // used in AarManifestTransformerTask.kt for unziping
     implementation(libs.toml)
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
index 7259c36..26930dd 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
@@ -129,10 +129,10 @@
 
         if (dynamicRangeResolver.is10BitDynamicRangeSupported()) {
             generate10BitSupportedCombinationList()
+        }
 
-            if (isUltraHdrSupported()) {
-                generateUltraHdrSupportedCombinationList()
-            }
+        if (isUltraHdrSupported()) {
+            generateUltraHdrSupportedCombinationList()
         }
 
         if (isPreviewStabilizationSupported) {
@@ -194,7 +194,12 @@
             return featureSettingsToSupportedCombinationsMap[featureSettings]!!
         }
         var supportedSurfaceCombinations: MutableList<SurfaceCombination> = mutableListOf()
-        if (featureSettings.requiredMaxBitDepth == DynamicRange.BIT_DEPTH_8_BIT) {
+        if (featureSettings.isUltraHdrOn) {
+            // For Ultra HDR output, only the default camera mode is currently supported.
+            if (featureSettings.cameraMode == CameraMode.DEFAULT) {
+                supportedSurfaceCombinations.addAll(surfaceCombinationsUltraHdr)
+            }
+        } else if (featureSettings.requiredMaxBitDepth == DynamicRange.BIT_DEPTH_8_BIT) {
             when (featureSettings.cameraMode) {
                 CameraMode.CONCURRENT_CAMERA ->
                     supportedSurfaceCombinations = concurrentSurfaceCombinations
@@ -213,11 +218,7 @@
         } else if (featureSettings.requiredMaxBitDepth == DynamicRange.BIT_DEPTH_10_BIT) {
             // For 10-bit outputs, only the default camera mode is currently supported.
             if (featureSettings.cameraMode == CameraMode.DEFAULT) {
-                if (featureSettings.isUltraHdrOn) {
-                    supportedSurfaceCombinations.addAll(surfaceCombinationsUltraHdr)
-                } else {
-                    supportedSurfaceCombinations.addAll(surfaceCombinations10Bit)
-                }
+                supportedSurfaceCombinations.addAll(surfaceCombinations10Bit)
             }
         }
         featureSettingsToSupportedCombinationsMap[featureSettings] = supportedSurfaceCombinations
@@ -393,6 +394,11 @@
         isPreviewStabilizationOn: Boolean,
         isUltraHdrOn: Boolean
     ): FeatureSettings {
+        require(!(cameraMode != CameraMode.DEFAULT && isUltraHdrOn)) {
+            "Camera device Id is $cameraId. Ultra HDR is not " +
+                "currently supported in ${CameraMode.toLabelString(cameraMode)} camera mode."
+        }
+
         val requiredMaxBitDepth = getRequiredMaxBitDepth(resolvedDynamicRanges)
         require(
             !(cameraMode != CameraMode.DEFAULT &&
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/CameraCompatModule.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/CameraCompatModule.kt
index 577e4db..83c1aa3 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/CameraCompatModule.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/CameraCompatModule.kt
@@ -18,6 +18,7 @@
 
 import androidx.camera.camera2.pipe.integration.compat.workaround.AutoFlashAEModeDisabler
 import androidx.camera.camera2.pipe.integration.compat.workaround.InactiveSurfaceCloser
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage
 import androidx.camera.camera2.pipe.integration.compat.workaround.MeteringRegionCorrection
 import androidx.camera.camera2.pipe.integration.compat.workaround.TemplateParamsOverride
 import androidx.camera.camera2.pipe.integration.compat.workaround.UseFlashModeTorchFor3aUpdate
@@ -34,6 +35,7 @@
             UseFlashModeTorchFor3aUpdate.Bindings::class,
             UseTorchAsFlash.Bindings::class,
             TemplateParamsOverride.Bindings::class,
+            Lock3ABehaviorWhenCaptureImage.Bindings::class,
         ],
 )
 public abstract class CameraCompatModule
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatBaseImpl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatBaseImpl.kt
index ec7f41f..7aa48d6 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatBaseImpl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatBaseImpl.kt
@@ -19,14 +19,26 @@
 import android.graphics.SurfaceTexture
 import android.hardware.camera2.params.StreamConfigurationMap
 import android.util.Size
+import androidx.camera.core.Logger
 import androidx.camera.core.impl.ImageFormatConstants
 
+private const val TAG = "StreamConfigurationMapCompatBaseImpl"
+
 internal open class StreamConfigurationMapCompatBaseImpl(
     val streamConfigurationMap: StreamConfigurationMap?
 ) : StreamConfigurationMapCompat.StreamConfigurationMapCompatImpl {
 
     override fun getOutputFormats(): Array<Int>? {
-        return streamConfigurationMap?.outputFormats?.toTypedArray()
+        // b/361590210: try-catch to workaround the NullPointerException issue when using
+        // StreamConfigurationMap provided by Robolectric.
+        val outputFormats =
+            try {
+                streamConfigurationMap?.outputFormats
+            } catch (e: NullPointerException) {
+                Logger.e(TAG, "Failed to get output formats from StreamConfigurationMap", e)
+                null
+            }
+        return outputFormats?.toTypedArray()
     }
 
     override fun getOutputSizes(format: Int): Array<Size>? {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt
index 7988db32..81e63e1 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt
@@ -240,6 +240,14 @@
         ) {
             quirks.add(ImageCaptureFailedForVideoSnapshotQuirk())
         }
+        if (
+            quirkSettings.shouldEnableQuirk(
+                LockAeAndCaptureImageBreakCameraQuirk::class.java,
+                LockAeAndCaptureImageBreakCameraQuirk.isEnabled(cameraMetadata)
+            )
+        ) {
+            quirks.add(LockAeAndCaptureImageBreakCameraQuirk())
+        }
 
         Quirks(quirks).also {
             Logger.d(TAG, "camera2-pipe-integration CameraQuirks = " + Quirks.toString(it))
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/LockAeAndCaptureImageBreakCameraQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/LockAeAndCaptureImageBreakCameraQuirk.kt
new file mode 100644
index 0000000..95ba980
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/LockAeAndCaptureImageBreakCameraQuirk.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.integration.compat.quirk
+
+import android.annotation.SuppressLint
+import android.hardware.camera2.CameraCharacteristics.LENS_FACING
+import android.hardware.camera2.CameraMetadata.LENS_FACING_BACK
+import android.os.Build
+import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage
+import androidx.camera.core.impl.Quirk
+
+/**
+ * QuirkSummary
+ * - Bug Id: b/360106037
+ * - Description: Quirk indicating that locking AE (Auto Exposure) and taking pictures can lead to
+ *   an abnormal camera service state on Pixel 3 back camera. Although the picture is successfully
+ *   taken, the camera service becomes unresponsive without any error callbacks. Reopening the
+ *   camera can restore its functionality.
+ * - Device(s): Pixel 3.
+ *
+ * @see Lock3ABehaviorWhenCaptureImage
+ */
+@SuppressLint("CameraXQuirksClassDetector")
+public class LockAeAndCaptureImageBreakCameraQuirk : Quirk {
+
+    public companion object {
+        public fun isEnabled(cameraMetadata: CameraMetadata): Boolean {
+            return isPixel3 && cameraMetadata[LENS_FACING] == LENS_FACING_BACK
+        }
+
+        private val isPixel3: Boolean
+            get() = "Pixel 3".equals(Build.MODEL, ignoreCase = true)
+    }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/workaround/Lock3ABehaviorWhenCaptureImage.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/workaround/Lock3ABehaviorWhenCaptureImage.kt
new file mode 100644
index 0000000..f893efd
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/workaround/Lock3ABehaviorWhenCaptureImage.kt
@@ -0,0 +1,106 @@
+/*
+ * 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.integration.compat.workaround
+
+import androidx.camera.camera2.pipe.Lock3ABehavior
+import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
+import androidx.camera.camera2.pipe.integration.compat.quirk.LockAeAndCaptureImageBreakCameraQuirk
+import dagger.Module
+import dagger.Provides
+
+/**
+ * Provides customized 3A lock behaviors before capturing an image.
+ *
+ * @property hasAeLockBehavior Indicates whether there is a specific AE (Auto Exposure) lock
+ *   behavior defined. If true, the [aeLockBehavior] will be used; otherwise, the default AE
+ *   behavior will be applied.
+ * @property aeLockBehavior The specific AE lock behavior to apply if [hasAeLockBehavior] is true.
+ *   If null and [hasAeLockBehavior] is true, AE lock will be effectively disabled.
+ * @property hasAfLockBehavior Indicates whether there is a specific AF (Auto Focus) lock behavior
+ *   defined. If true, the [afLockBehavior] will be used; otherwise, the default AF behavior will be
+ *   applied.
+ * @property afLockBehavior The specific AF lock behavior to apply if [hasAfLockBehavior] is true.
+ *   If null and [hasAfLockBehavior] is true, AF lock will be effectively disabled.
+ * @property hasAwbLockBehavior Indicates whether there is a specific AWB (Auto White Balance) lock
+ *   behavior defined. If true, the [awbLockBehavior] will be used; otherwise, the default AWB
+ *   behavior will be applied.
+ * @property awbLockBehavior The specific AWB lock behavior to apply if [hasAwbLockBehavior] is
+ *   true. If null and [hasAwbLockBehavior] is true, AWB lock will be effectively disabled.
+ * @see LockAeAndCaptureImageBreakCameraQuirk
+ */
+public class Lock3ABehaviorWhenCaptureImage(
+    private val hasAeLockBehavior: Boolean = false,
+    private val aeLockBehavior: Lock3ABehavior? = null,
+    private val hasAfLockBehavior: Boolean = false,
+    private val afLockBehavior: Lock3ABehavior? = null,
+    private val hasAwbLockBehavior: Boolean = false,
+    private val awbLockBehavior: Lock3ABehavior? = null,
+) {
+
+    /**
+     * Gets customized 3A lock behaviors, using provided defaults if no specific behavior is set.
+     *
+     * This method checks the `has*LockBehavior` properties to determine if a custom behavior is
+     * defined for each 3A lock type (AE, AF, AWB). If a custom behavior is defined, it will be
+     * returned; otherwise, the corresponding `default*Behavior` will be used.
+     *
+     * @param defaultAeBehavior Default AE lock behavior if none is specified.
+     * @param defaultAfBehavior Default AF lock behavior if none is specified.
+     * @param defaultAwbBehavior Default AWB lock behavior if none is specified.
+     * @return A Triple containing the customized AE, AF, and AWB lock behaviors.
+     */
+    public fun getLock3ABehaviors(
+        defaultAeBehavior: Lock3ABehavior? = null,
+        defaultAfBehavior: Lock3ABehavior? = null,
+        defaultAwbBehavior: Lock3ABehavior? = null
+    ): Triple<Lock3ABehavior?, Lock3ABehavior?, Lock3ABehavior?> =
+        Triple(
+            if (hasAeLockBehavior) aeLockBehavior else defaultAeBehavior,
+            if (hasAfLockBehavior) afLockBehavior else defaultAfBehavior,
+            if (hasAwbLockBehavior) awbLockBehavior else defaultAwbBehavior
+        )
+
+    @Module
+    public abstract class Bindings {
+        public companion object {
+            @Provides
+            public fun provideLock3ABehaviorBeforeCaptureImage(
+                cameraQuirks: CameraQuirks
+            ): Lock3ABehaviorWhenCaptureImage =
+                if (
+                    cameraQuirks.quirks.contains(LockAeAndCaptureImageBreakCameraQuirk::class.java)
+                ) {
+                    doNotLockAe3ABehavior
+                } else {
+                    noCustomizedLock3ABehavior
+                }
+        }
+    }
+
+    public companion object {
+        public val noCustomizedLock3ABehavior: Lock3ABehaviorWhenCaptureImage by lazy {
+            Lock3ABehaviorWhenCaptureImage()
+        }
+
+        public val doNotLockAe3ABehavior: Lock3ABehaviorWhenCaptureImage by lazy {
+            Lock3ABehaviorWhenCaptureImage(
+                hasAeLockBehavior = true,
+                aeLockBehavior = null // Explicitly disable AE lock
+            )
+        }
+    }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CapturePipeline.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CapturePipeline.kt
index 372696c..1d21a90 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CapturePipeline.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CapturePipeline.kt
@@ -49,6 +49,7 @@
 import androidx.camera.camera2.pipe.core.Log.debug
 import androidx.camera.camera2.pipe.core.Log.info
 import androidx.camera.camera2.pipe.integration.adapter.CaptureConfigAdapter
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage
 import androidx.camera.camera2.pipe.integration.compat.workaround.UseTorchAsFlash
 import androidx.camera.camera2.pipe.integration.compat.workaround.isFlashAvailable
 import androidx.camera.camera2.pipe.integration.compat.workaround.shouldStopRepeatingBeforeCapture
@@ -110,6 +111,7 @@
     private val threads: UseCaseThreads,
     private val requestListener: ComboRequestListener,
     private val useTorchAsFlash: UseTorchAsFlash,
+    private val lock3ABehaviorWhenCaptureImage: Lock3ABehaviorWhenCaptureImage,
     cameraProperties: CameraProperties,
     private val useCaseCameraState: UseCaseCameraState,
     useCaseGraphConfig: UseCaseGraphConfig,
@@ -378,10 +380,16 @@
         graph
             .acquireSession()
             .use {
+                val (aeLockBehavior, afLockBehavior, awbLockBehavior) =
+                    lock3ABehaviorWhenCaptureImage.getLock3ABehaviors(
+                        defaultAeBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN,
+                        defaultAfBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN,
+                        defaultAwbBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN,
+                    )
                 it.lock3A(
-                    aeLockBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN,
-                    afLockBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN,
-                    awbLockBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN,
+                    aeLockBehavior = aeLockBehavior,
+                    afLockBehavior = afLockBehavior,
+                    awbLockBehavior = awbLockBehavior,
                     convergedTimeLimitNs = convergedTimeLimitNs,
                     lockedTimeLimitNs = CHECK_3A_TIMEOUT_IN_NS
                 )
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt
index de128bc..0731bda 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraRequestControl.kt
@@ -354,9 +354,9 @@
         runIfNotClosed {
             useGraphSessionOrFailed {
                 it.update3A(
-                    aeRegions = METERING_REGIONS_DEFAULT.asList(),
-                    afRegions = METERING_REGIONS_DEFAULT.asList(),
-                    awbRegions = METERING_REGIONS_DEFAULT.asList()
+                    aeRegions = aeRegions ?: METERING_REGIONS_DEFAULT.asList(),
+                    afRegions = afRegions ?: METERING_REGIONS_DEFAULT.asList(),
+                    awbRegions = awbRegions ?: METERING_REGIONS_DEFAULT.asList()
                 )
             }
         } ?: submitFailedResult
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
index 92be8fb..5d25a6d 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
@@ -1655,16 +1655,34 @@
         }
     }
 
+    @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    @Test
+    fun checkUltraHdrCombinationsSupported_when8bit() {
+        // Device might support Ultra HDR but not 10-bit.
+        setupCamera(supportedFormats = intArrayOf(JPEG_R))
+        val supportedSurfaceCombination =
+            SupportedSurfaceCombination(context, fakeCameraMetadata, mockEncoderProfilesAdapter)
+
+        GuaranteedConfigurationsUtil.getUltraHdrSupportedCombinationList().forEach {
+            assertThat(
+                    supportedSurfaceCombination.checkSupported(
+                        SupportedSurfaceCombination.FeatureSettings(
+                            CameraMode.DEFAULT,
+                            requiredMaxBitDepth = DynamicRange.BIT_DEPTH_8_BIT,
+                            isUltraHdrOn = true
+                        ),
+                        it.surfaceConfigList
+                    )
+                )
+                .isTrue()
+        }
+    }
+
     /** JPEG_R/MAXIMUM when Ultra HDR is ON. */
     @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     @Test
     fun canSelectCorrectSizes_onlyJpegr_whenUltraHdrIsOn() {
-        val jpegUseCase =
-            createUseCase(
-                CaptureType.IMAGE_CAPTURE,
-                dynamicRange = HLG_10_BIT,
-                imageFormat = JPEG_R
-            ) // JPEG
+        val jpegUseCase = createUseCase(CaptureType.IMAGE_CAPTURE, imageFormat = JPEG_R) // JPEG
         val useCaseExpectedResultMap =
             mutableMapOf<UseCase, Size>().apply { put(jpegUseCase, maximumSize) }
         getSuggestedSpecsAndVerify(
@@ -1683,7 +1701,27 @@
         val jpegUseCase =
             createUseCase(
                 CaptureType.IMAGE_CAPTURE,
-                dynamicRange = HLG_10_BIT,
+                imageFormat = JPEG_R,
+            ) // JPEG
+        val useCaseExpectedResultMap =
+            mutableMapOf<UseCase, Size>().apply {
+                put(privUseCase, previewSize)
+                put(jpegUseCase, maximumSize)
+            }
+        getSuggestedSpecsAndVerify(
+            useCasesExpectedResultMap = useCaseExpectedResultMap,
+            supportedOutputFormats = intArrayOf(JPEG_R),
+        )
+    }
+
+    /** HLG10 PRIV/PREVIEW + JPEG_R/MAXIMUM when Ultra HDR is ON. */
+    @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    @Test
+    fun canSelectCorrectSizes_hlg10PrivPlusJpegr_whenUltraHdrIsOn() {
+        val privUseCase = createUseCase(CaptureType.PREVIEW, dynamicRange = HLG_10_BIT) // PRIV
+        val jpegUseCase =
+            createUseCase(
+                CaptureType.IMAGE_CAPTURE,
                 imageFormat = JPEG_R,
             ) // JPEG
         val useCaseExpectedResultMap =
@@ -1708,7 +1746,6 @@
         val jpegUseCase =
             createUseCase(
                 CaptureType.IMAGE_CAPTURE,
-                dynamicRange = HLG_10_BIT,
                 imageFormat = JPEG_R,
             ) // JPEG
         val useCaseExpectedResultMap =
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatTest.kt
index 3e8cf9f..4b07606 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/StreamConfigurationMapCompatTest.kt
@@ -98,4 +98,22 @@
         assertThat(streamConfigurationMapCompat.getHighResolutionOutputSizes(ImageFormat.JPEG))
             .isNull()
     }
+
+    @Test
+    fun getOutputFormats_notThrowingNullPointerException() {
+        val builder = StreamConfigurationMapBuilder.newBuilder()
+        val compat =
+            StreamConfigurationMapCompat(
+                builder.build(),
+                OutputSizesCorrector(FakeCameraMetadata(), builder.build())
+            )
+
+        // b/361590210: check the workaround for NullPointerException issue (on API 23+) of
+        // StreamConfigurationMap provided by Robolectric is applied.
+        if (Build.VERSION.SDK_INT >= 23) {
+            assertThat(compat.getOutputFormats()).isNull()
+        } else {
+            assertThat(compat.getOutputFormats()).isNotNull()
+        }
+    }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/workaround/Lock3ABehaviorWhenCaptureImageTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/workaround/Lock3ABehaviorWhenCaptureImageTest.kt
new file mode 100644
index 0000000..206bca8
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/workaround/Lock3ABehaviorWhenCaptureImageTest.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.integration.compat.workaround
+
+import androidx.camera.camera2.pipe.Lock3ABehavior
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+class Lock3ABehaviorWhenCaptureImageTest {
+
+    @Test
+    fun getLock3ABehaviors_noCustomBehaviors_returnsDefaults() {
+        val lock3ABehavior = Lock3ABehaviorWhenCaptureImage()
+        val defaultAeBehavior = null
+        val defaultAfBehavior = Lock3ABehavior.AFTER_NEW_SCAN
+        val defaultAwbBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN
+
+        val (ae, af, awb) =
+            lock3ABehavior.getLock3ABehaviors(
+                defaultAeBehavior,
+                defaultAfBehavior,
+                defaultAwbBehavior
+            )
+
+        assertThat(ae).isEqualTo(defaultAeBehavior)
+        assertThat(af).isEqualTo(defaultAfBehavior)
+        assertThat(awb).isEqualTo(defaultAwbBehavior)
+    }
+
+    @Test
+    fun getLock3ABehaviors_withCustomBehaviors_returnsCustom() {
+        val customAeBehavior = null
+        val customAfBehavior = Lock3ABehavior.AFTER_NEW_SCAN
+        val customAwbBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN
+        val lock3ABehavior =
+            Lock3ABehaviorWhenCaptureImage(
+                hasAeLockBehavior = true,
+                aeLockBehavior = customAeBehavior,
+                hasAfLockBehavior = true,
+                afLockBehavior = customAfBehavior,
+                hasAwbLockBehavior = true,
+                awbLockBehavior = customAwbBehavior
+            )
+
+        val (ae, af, awb) = lock3ABehavior.getLock3ABehaviors() // No defaults needed
+
+        assertThat(ae).isEqualTo(customAeBehavior)
+        assertThat(af).isEqualTo(customAfBehavior)
+        assertThat(awb).isEqualTo(customAwbBehavior)
+    }
+
+    @Test
+    fun getLock3ABehaviors_mixedBehaviors_returnsCorrectly() {
+        val customAfBehavior = Lock3ABehavior.AFTER_NEW_SCAN
+        val lock3ABehavior =
+            Lock3ABehaviorWhenCaptureImage(
+                hasAfLockBehavior = true,
+                afLockBehavior = customAfBehavior
+            )
+        val defaultAeBehavior = null
+        val defaultAwbBehavior = Lock3ABehavior.AFTER_CURRENT_SCAN
+
+        val (ae, af, awb) =
+            lock3ABehavior.getLock3ABehaviors(
+                defaultAeBehavior,
+                defaultAwbBehavior = defaultAwbBehavior
+            )
+
+        assertThat(ae).isEqualTo(defaultAeBehavior) // Default used
+        assertThat(af).isEqualTo(customAfBehavior) // Custom used
+        assertThat(awb).isEqualTo(defaultAwbBehavior) // Default used
+    }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/CapturePipelineTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/CapturePipelineTest.kt
index 35fb7e0..f968130 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/CapturePipelineTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/CapturePipelineTest.kt
@@ -48,11 +48,15 @@
 import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
 import androidx.camera.camera2.pipe.integration.compat.workaround.AeFpsRange
 import androidx.camera.camera2.pipe.integration.compat.workaround.CapturePipelineTorchCorrection
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage.Companion.doNotLockAe3ABehavior
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage.Companion.noCustomizedLock3ABehavior
 import androidx.camera.camera2.pipe.integration.compat.workaround.NoOpAutoFlashAEModeDisabler
 import androidx.camera.camera2.pipe.integration.compat.workaround.NoOpTemplateParamsOverride
 import androidx.camera.camera2.pipe.integration.compat.workaround.NotUseFlashModeTorchFor3aUpdate
 import androidx.camera.camera2.pipe.integration.compat.workaround.NotUseTorchAsFlash
 import androidx.camera.camera2.pipe.integration.compat.workaround.OutputSizesCorrector
+import androidx.camera.camera2.pipe.integration.compat.workaround.UseTorchAsFlash
 import androidx.camera.camera2.pipe.integration.compat.workaround.UseTorchAsFlashImpl
 import androidx.camera.camera2.pipe.integration.config.UseCaseGraphConfig
 import androidx.camera.camera2.pipe.integration.interop.CaptureRequestOptions
@@ -153,6 +157,9 @@
             var waitForAwbAtLock3AForCapture: Boolean = false
 
             var cancelAfAtUnlock3AForCapture: Boolean = false
+            var aeLockBehavior: Lock3ABehavior? = null
+            var afLockBehavior: Lock3ABehavior? = null
+            var awbLockBehavior: Lock3ABehavior? = null
 
             override suspend fun lock3A(
                 aeMode: AeMode?,
@@ -171,6 +178,9 @@
                 convergedTimeLimitNs: Long,
                 lockedTimeLimitNs: Long
             ): Deferred<Result3A> {
+                this.aeLockBehavior = aeLockBehavior
+                this.afLockBehavior = afLockBehavior
+                this.awbLockBehavior = awbLockBehavior
                 lock3ASemaphore.release()
                 return CompletableDeferred(Result3A(Result3A.Status.OK))
             }
@@ -359,19 +369,7 @@
                 templateParamsOverride = NoOpTemplateParamsOverride,
             )
 
-        capturePipeline =
-            CapturePipelineImpl(
-                configAdapter = fakeCaptureConfigAdapter,
-                cameraProperties = fakeCameraProperties,
-                requestListener = comboRequestListener,
-                threads = fakeUseCaseThreads,
-                torchControl = torchControl,
-                useCaseGraphConfig = fakeUseCaseGraphConfig,
-                useCaseCameraState = fakeUseCaseCameraState,
-                useTorchAsFlash = NotUseTorchAsFlash,
-                sessionProcessorManager = null,
-                flashControl = flashControl,
-            )
+        capturePipeline = createCapturePipeline()
     }
 
     @After
@@ -475,19 +473,7 @@
 
     private suspend fun TestScope.withTorchAsFlashQuirk_shouldOpenTorch(imageCaptureMode: Int) {
         // Arrange.
-        capturePipeline =
-            CapturePipelineImpl(
-                configAdapter = fakeCaptureConfigAdapter,
-                cameraProperties = fakeCameraProperties,
-                requestListener = comboRequestListener,
-                threads = fakeUseCaseThreads,
-                torchControl = torchControl,
-                useCaseGraphConfig = fakeUseCaseGraphConfig,
-                useCaseCameraState = fakeUseCaseCameraState,
-                useTorchAsFlash = UseTorchAsFlashImpl,
-                sessionProcessorManager = null,
-                flashControl = flashControl,
-            )
+        capturePipeline = createCapturePipeline(useTorchAsFlash = UseTorchAsFlashImpl)
 
         val requestList = mutableListOf<Request>()
         fakeCameraGraphSession.requestHandler = { requests -> requestList.addAll(requests) }
@@ -602,22 +588,69 @@
     @Test
     fun miniLatency_flashRequired_withFlashTypeTorch_shouldLock3A(): Unit = runTest {
         withFlashTypeTorch_shouldLock3A(
+            capturePipeline,
             ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY,
-            ImageCapture.FLASH_MODE_ON
+            ImageCapture.FLASH_MODE_ON,
+            expectedLock3ABehaviors =
+                Triple(
+                    Lock3ABehavior.AFTER_CURRENT_SCAN,
+                    Lock3ABehavior.AFTER_CURRENT_SCAN,
+                    Lock3ABehavior.AFTER_CURRENT_SCAN
+                )
         )
     }
 
     @Test
+    fun miniLatency_flashRequired_withFlashTypeTorch_doNotLockAe3ABehavior_shouldLock3A(): Unit =
+        runTest {
+            val capturePipeline =
+                createCapturePipeline(lock3ABehaviorWhenCaptureImage = doNotLockAe3ABehavior)
+            withFlashTypeTorch_shouldLock3A(
+                capturePipeline,
+                ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY,
+                ImageCapture.FLASH_MODE_ON,
+                expectedLock3ABehaviors =
+                    Triple(
+                        null,
+                        Lock3ABehavior.AFTER_CURRENT_SCAN,
+                        Lock3ABehavior.AFTER_CURRENT_SCAN
+                    )
+            )
+        }
+
+    @Test
     fun maxQuality_withFlashTypeTorch_shouldLock3A(): Unit = runTest {
         withFlashTypeTorch_shouldLock3A(
+            capturePipeline,
             ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY,
-            ImageCapture.FLASH_MODE_OFF
+            ImageCapture.FLASH_MODE_OFF,
+            expectedLock3ABehaviors =
+                Triple(
+                    Lock3ABehavior.AFTER_CURRENT_SCAN,
+                    Lock3ABehavior.AFTER_CURRENT_SCAN,
+                    Lock3ABehavior.AFTER_CURRENT_SCAN
+                )
+        )
+    }
+
+    @Test
+    fun maxQuality_withFlashTypeTorch_doNotLockAe3ABehavior_shouldLock3A(): Unit = runTest {
+        val capturePipeline =
+            createCapturePipeline(lock3ABehaviorWhenCaptureImage = doNotLockAe3ABehavior)
+        withFlashTypeTorch_shouldLock3A(
+            capturePipeline,
+            ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY,
+            ImageCapture.FLASH_MODE_OFF,
+            expectedLock3ABehaviors =
+                Triple(null, Lock3ABehavior.AFTER_CURRENT_SCAN, Lock3ABehavior.AFTER_CURRENT_SCAN)
         )
     }
 
     private suspend fun TestScope.withFlashTypeTorch_shouldLock3A(
+        capturePipeline: CapturePipeline,
         imageCaptureMode: Int,
-        flashMode: Int
+        flashMode: Int,
+        expectedLock3ABehaviors: Triple<Lock3ABehavior?, Lock3ABehavior?, Lock3ABehavior?>,
     ) {
         // Arrange.
         val requestList = mutableListOf<Request>()
@@ -636,6 +669,10 @@
         // Assert 1, should call lock3A, but not call unlock3A (before capturing is finished).
         assertThat(fakeCameraGraphSession.lock3ASemaphore.tryAcquire(this)).isTrue()
         assertThat(fakeCameraGraphSession.unlock3ASemaphore.tryAcquire(this)).isFalse()
+        // Ensure correct Lock3ABehaviors are set.
+        assertThat(fakeCameraGraphSession.aeLockBehavior).isEqualTo(expectedLock3ABehaviors.first)
+        assertThat(fakeCameraGraphSession.afLockBehavior).isEqualTo(expectedLock3ABehaviors.second)
+        assertThat(fakeCameraGraphSession.awbLockBehavior).isEqualTo(expectedLock3ABehaviors.third)
 
         // Complete the capture request.
         assertThat(fakeCameraGraphSession.submitSemaphore.tryAcquire(this)).isTrue()
@@ -1221,6 +1258,24 @@
         assertThat(screenFlash.awaitClear(3000)).isTrue()
     }
 
+    private fun createCapturePipeline(
+        useTorchAsFlash: UseTorchAsFlash = NotUseTorchAsFlash,
+        lock3ABehaviorWhenCaptureImage: Lock3ABehaviorWhenCaptureImage = noCustomizedLock3ABehavior
+    ) =
+        CapturePipelineImpl(
+            configAdapter = fakeCaptureConfigAdapter,
+            cameraProperties = fakeCameraProperties,
+            requestListener = comboRequestListener,
+            threads = fakeUseCaseThreads,
+            torchControl = torchControl,
+            useCaseGraphConfig = fakeUseCaseGraphConfig,
+            useCaseCameraState = fakeUseCaseCameraState,
+            useTorchAsFlash = useTorchAsFlash,
+            lock3ABehaviorWhenCaptureImage = lock3ABehaviorWhenCaptureImage,
+            sessionProcessorManager = null,
+            flashControl = flashControl,
+        )
+
     // TODO(wenhungteng@): Porting overrideAeModeForStillCapture_quirkAbsent_notOverride,
     //  overrideAeModeForStillCapture_aePrecaptureStarted_override,
     //  overrideAeModeForStillCapture_aePrecaptureFinish_notOverride,
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/StillCaptureRequestTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/StillCaptureRequestTest.kt
index a62aef8..5698804 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/StillCaptureRequestTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/StillCaptureRequestTest.kt
@@ -23,6 +23,7 @@
 import androidx.camera.camera2.pipe.integration.adapter.CaptureConfigAdapter
 import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
 import androidx.camera.camera2.pipe.integration.adapter.ZslControlNoOpImpl
+import androidx.camera.camera2.pipe.integration.compat.workaround.Lock3ABehaviorWhenCaptureImage.Companion.noCustomizedLock3ABehavior
 import androidx.camera.camera2.pipe.integration.compat.workaround.NoOpTemplateParamsOverride
 import androidx.camera.camera2.pipe.integration.compat.workaround.NotUseFlashModeTorchFor3aUpdate
 import androidx.camera.camera2.pipe.integration.compat.workaround.NotUseTorchAsFlash
@@ -435,6 +436,7 @@
                         useCaseGraphConfig = fakeUseCaseGraphConfig,
                         useCaseCameraState = fakeUseCaseCameraState,
                         useTorchAsFlash = NotUseTorchAsFlash,
+                        lock3ABehaviorWhenCaptureImage = noCustomizedLock3ABehavior,
                         sessionProcessorManager = null,
                         flashControl =
                             FlashControl(
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
index 2f89dcf..630a50a 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
@@ -182,10 +182,10 @@
 
         if (mDynamicRangeResolver.is10BitDynamicRangeSupported()) {
             generate10BitSupportedCombinationList();
+        }
 
-            if (isUltraHdrSupported()) {
-                generateUltraHdrSupportedCombinationList();
-            }
+        if (isUltraHdrSupported()) {
+            generateUltraHdrSupportedCombinationList();
         }
 
         mIsStreamUseCaseSupported = StreamUseCaseUtil.isStreamUseCaseSupported(mCharacteristics);
@@ -288,7 +288,12 @@
 
         List<SurfaceCombination> supportedSurfaceCombinations = new ArrayList<>();
 
-        if (featureSettings.getRequiredMaxBitDepth() == DynamicRange.BIT_DEPTH_8_BIT) {
+        if (featureSettings.isUltraHdrOn()) {
+            // For Ultra HDR output, only the default camera mode is currently supported.
+            if (featureSettings.getCameraMode() == CameraMode.DEFAULT) {
+                supportedSurfaceCombinations.addAll(mSurfaceCombinationsUltraHdr);
+            }
+        } else if (featureSettings.getRequiredMaxBitDepth() == DynamicRange.BIT_DEPTH_8_BIT) {
             switch (featureSettings.getCameraMode()) {
                 case CameraMode.CONCURRENT_CAMERA:
                     supportedSurfaceCombinations = mConcurrentSurfaceCombinations;
@@ -305,11 +310,7 @@
         } else if (featureSettings.getRequiredMaxBitDepth() == DynamicRange.BIT_DEPTH_10_BIT) {
             // For 10-bit outputs, only the default camera mode is currently supported.
             if (featureSettings.getCameraMode() == CameraMode.DEFAULT) {
-                if (featureSettings.isUltraHdrOn()) {
-                    supportedSurfaceCombinations.addAll(mSurfaceCombinationsUltraHdr);
-                } else {
-                    supportedSurfaceCombinations.addAll(mSurfaceCombinations10Bit);
-                }
+                supportedSurfaceCombinations.addAll(mSurfaceCombinations10Bit);
             }
         }
 
@@ -865,6 +866,13 @@
             boolean isPreviewStabilizationOn, boolean isUltraHdrOn) {
         int requiredMaxBitDepth = getRequiredMaxBitDepth(resolvedDynamicRanges);
 
+        if (cameraMode != CameraMode.DEFAULT && isUltraHdrOn) {
+            throw new IllegalArgumentException(String.format("Camera device id is %s. Ultra HDR "
+                            + "is not currently supported in %s camera mode.",
+                    mCameraId,
+                    CameraMode.toLabelString(cameraMode)));
+        }
+
         if (cameraMode != CameraMode.DEFAULT
                 && requiredMaxBitDepth == DynamicRange.BIT_DEPTH_10_BIT) {
             throw new IllegalArgumentException(String.format("Camera device id is %s. 10 bit "
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatBaseImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatBaseImpl.java
index 3b97170..ec4cc78 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatBaseImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatBaseImpl.java
@@ -24,11 +24,14 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
 import androidx.camera.core.impl.ImageFormatConstants;
 
 class StreamConfigurationMapCompatBaseImpl
         implements StreamConfigurationMapCompat.StreamConfigurationMapCompatImpl {
 
+    private static final String TAG = "StreamConfigurationMapCompatBaseImpl";
+
     final StreamConfigurationMap mStreamConfigurationMap;
 
     StreamConfigurationMapCompatBaseImpl(@NonNull StreamConfigurationMap map) {
@@ -38,7 +41,14 @@
     @Nullable
     @Override
     public int[] getOutputFormats() {
-        return mStreamConfigurationMap.getOutputFormats();
+        // b/361590210: try-catch to workaround the NullPointerException issue when using
+        // StreamConfigurationMap provided by Robolectric.
+        try {
+            return mStreamConfigurationMap.getOutputFormats();
+        } catch (NullPointerException e) {
+            Logger.e(TAG, "Failed to get output formats from StreamConfigurationMap", e);
+            return null;
+        }
     }
 
     @Nullable
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
index b4059b9..d665ba5 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
@@ -1739,6 +1739,7 @@
     // Resolution selection tests for Ultra HDR
     //
     // //////////////////////////////////////////////////////////////////////////////////////////
+
     @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     @Test
     fun checkUltraHdrCombinationsSupported() {
@@ -1768,6 +1769,33 @@
         }
     }
 
+    @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    @Test
+    fun checkUltraHdrCombinationsSupported_when8bit() {
+        // Device might support Ultra HDR but not 10-bit.
+        setupCameraAndInitCameraX(supportedFormats = intArrayOf(JPEG_R))
+        val supportedSurfaceCombination =
+            SupportedSurfaceCombination(
+                context,
+                DEFAULT_CAMERA_ID,
+                cameraManagerCompat!!,
+                mockCamcorderProfileHelper
+            )
+
+        GuaranteedConfigurationsUtil.getUltraHdrSupportedCombinationList().forEach {
+            assertThat(
+                    supportedSurfaceCombination.checkSupported(
+                        createFeatureSettings(
+                            requiredMaxBitDepth = BIT_DEPTH_8_BIT,
+                            isUltraHdrOn = true
+                        ),
+                        it.surfaceConfigList
+                    )
+                )
+                .isTrue()
+        }
+    }
+
     /** JPEG_R/MAXIMUM when Ultra HDR is ON. */
     @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     @Test
@@ -1775,7 +1803,6 @@
         val jpegUseCase =
             createUseCase(
                 CaptureType.IMAGE_CAPTURE,
-                dynamicRange = HLG_10_BIT,
                 imageFormat = JPEG_R,
             ) // JPEG
         val useCaseExpectedResultMap =
@@ -1796,7 +1823,27 @@
         val jpegUseCase =
             createUseCase(
                 CaptureType.IMAGE_CAPTURE,
-                dynamicRange = HLG_10_BIT,
+                imageFormat = JPEG_R,
+            ) // JPEG
+        val useCaseExpectedResultMap =
+            mutableMapOf<UseCase, Size>().apply {
+                put(privUseCase, PREVIEW_SIZE)
+                put(jpegUseCase, MAXIMUM_SIZE)
+            }
+        getSuggestedSpecsAndVerify(
+            useCasesExpectedSizeMap = useCaseExpectedResultMap,
+            supportedOutputFormats = intArrayOf(JPEG_R),
+        )
+    }
+
+    /** HLG10 PRIV/PREVIEW + JPEG_R/MAXIMUM when Ultra HDR is ON. */
+    @Config(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    @Test
+    fun canSelectCorrectSizes_hlg10PrivPlusJpegr_whenUltraHdrIsOn() {
+        val privUseCase = createUseCase(CaptureType.PREVIEW, dynamicRange = HLG_10_BIT) // PRIV
+        val jpegUseCase =
+            createUseCase(
+                CaptureType.IMAGE_CAPTURE,
                 imageFormat = JPEG_R,
             ) // JPEG
         val useCaseExpectedResultMap =
@@ -1821,7 +1868,6 @@
         val jpegUseCase =
             createUseCase(
                 CaptureType.IMAGE_CAPTURE,
-                dynamicRange = HLG_10_BIT,
                 imageFormat = JPEG_R,
             ) // JPEG
         val useCaseExpectedResultMap =
@@ -3489,10 +3535,8 @@
             set(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL, hardwareLevel)
             set(CameraCharacteristics.SENSOR_ORIENTATION, sensorOrientation)
             set(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize)
-            // Only setup stream configuration map when the supported output sizes are specified.
-            supportedSizes?.let {
-                set(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP, mockMap)
-            }
+            // Setup stream configuration map, no matter supported output sizes are specified.
+            set(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP, mockMap)
             set(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, deviceFPSRanges)
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                 dynamicRangeProfiles?.let {
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatTest.kt
index 29f150c..56f5d54 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/StreamConfigurationMapCompatTest.kt
@@ -100,4 +100,22 @@
         assertThat(streamConfigurationMapCompat.getHighResolutionOutputSizes(ImageFormat.JPEG))
             .isNull()
     }
+
+    @Test
+    fun getOutputFormats_notThrowingNullPointerException() {
+        val cameraId = "0"
+        val compat =
+            StreamConfigurationMapCompat.toStreamConfigurationMapCompat(
+                StreamConfigurationMapBuilder.newBuilder().build(),
+                OutputSizesCorrector(cameraId)
+            )
+
+        // b/361590210: check the workaround for NullPointerException issue (on API 23+) of
+        // StreamConfigurationMap provided by Robolectric is applied.
+        if (Build.VERSION.SDK_INT >= 23) {
+            assertThat(compat.getOutputFormats()).isNull()
+        } else {
+            assertThat(compat.getOutputFormats()).isNotNull()
+        }
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 5c15ced..20b2ecd 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -19,7 +19,6 @@
 import static android.graphics.ImageFormat.JPEG_R;
 
 import static androidx.camera.core.CameraEffect.IMAGE_CAPTURE;
-import static androidx.camera.core.DynamicRange.HDR_UNSPECIFIED_10_BIT;
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_BUFFER_FORMAT;
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_CAPTURE_CONFIG_UNPACKER;
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_DEFAULT_CAPTURE_CONFIG;
@@ -472,7 +471,7 @@
             if (isOutputFormatUltraHdr(builder.getMutableConfig())) {
                 builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT, JPEG_R);
                 builder.getMutableConfig().insertOption(OPTION_INPUT_DYNAMIC_RANGE,
-                        HDR_UNSPECIFIED_10_BIT);
+                        DynamicRange.UNSPECIFIED);
             } else if (useSoftwareJpeg) {
                 builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT,
                         ImageFormat.YUV_420_888);
@@ -2323,7 +2322,7 @@
                 if (isOutputFormatUltraHdr(getMutableConfig())) {
                     getMutableConfig().insertOption(OPTION_INPUT_FORMAT, JPEG_R);
                     getMutableConfig().insertOption(OPTION_INPUT_DYNAMIC_RANGE,
-                            HDR_UNSPECIFIED_10_BIT);
+                            DynamicRange.UNSPECIFIED);
                 } else {
                     getMutableConfig().insertOption(OPTION_INPUT_FORMAT, ImageFormat.JPEG);
                 }
@@ -2829,14 +2828,6 @@
          *
          * <p>If not set, the output format will default to {@link #OUTPUT_FORMAT_JPEG}.
          *
-         * <p>If an Ultra HDR output format is used, a {@link DynamicRange#HDR_UNSPECIFIED_10_BIT}
-         * will be used as the dynamic range of this use case. Please note that some devices may not
-         * be able to support configuring both SDR and HDR use cases at the same time, e.g. use
-         * Ultra HDR ImageCapture with a SDR Preview. Configuring concurrent SDR and HDR on these
-         * devices will result in an {@link IllegalArgumentException} to be thrown when invoking
-         * {@code bindToLifecycle()}. Such device specific constraints can be queried by calling
-         * {@link android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints(long)}.
-         *
          * @param outputFormat The output image format. Value is {@link #OUTPUT_FORMAT_JPEG} or
          *                     {@link #OUTPUT_FORMAT_JPEG_ULTRA_HDR}.
          * @return The current Builder.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
index 541a169..dc922ee 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -1031,9 +1031,16 @@
         // TODO(b/309900490): since there are other places (e.g. SupportedSurfaceCombination in
         //  camera2) that feature combination constraints are enforced, it would be nice if they
         //  followed a similar pattern for checking constraints.
-        if (hasExtension() && hasNonSdrConfig(useCases)) {
-            throw new IllegalArgumentException("Extensions are only supported for use with "
-                    + "standard dynamic range.");
+        if (hasExtension()) {
+            if (hasNonSdrConfig(useCases)) {
+                throw new IllegalArgumentException("Extensions are only supported for use with "
+                        + "standard dynamic range.");
+            }
+
+            if (hasUltraHdrImageCapture(useCases)) {
+                throw new IllegalArgumentException("Extensions are not supported for use with "
+                        + "Ultra HDR image capture.");
+            }
         }
 
         // TODO(b/322311893): throw exception to block feature combination of effect with Ultra
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeImageCaptureCallback.kt b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeOnImageCapturedCallback.kt
similarity index 64%
rename from camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeImageCaptureCallback.kt
rename to camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeOnImageCapturedCallback.kt
index b600a40..135f64c 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeImageCaptureCallback.kt
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeOnImageCapturedCallback.kt
@@ -25,14 +25,25 @@
 import androidx.camera.core.impl.utils.Exif
 import com.google.common.truth.Truth
 import java.io.ByteArrayInputStream
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.withTimeoutOrNull
 
-private const val CAPTURE_TIMEOUT = 15_000.toLong() //  15 seconds
+/**
+ * A fake implementation of the [ImageCapture.OnImageCapturedCallback] that is used for test.
+ *
+ * @param captureCount Number of captures to wait for.
+ * @property closeImageOnSuccess Whether to close images immediately on [onCaptureSuccess]
+ *   callbacks. This is true by default. If set to false, it is the user's responsibility to close
+ *   the images.
+ */
+public class FakeOnImageCapturedCallback(
+    captureCount: Int = 1,
+    private val closeImageOnSuccess: Boolean = true
+) : ImageCapture.OnImageCapturedCallback() {
+    public data class CapturedImage(val image: ImageProxy, val properties: ImageProperties)
 
-/** A fake implementation of the [ImageCapture.OnImageCapturedCallback] and used for test. */
-public class FakeImageCaptureCallback(captureCount: Int = 1) :
-    ImageCapture.OnImageCapturedCallback() {
     /** Data class of various image properties which are tested. */
     public data class ImageProperties(
         val size: Size? = null,
@@ -43,20 +54,34 @@
     )
 
     private val latch = CountdownDeferred(captureCount)
-    public val results: MutableList<ImageProperties> = mutableListOf()
+
+    /**
+     * List of [CapturedImage] obtained in [onCaptureSuccess] callback.
+     *
+     * If [closeImageOnSuccess] is true, the [CapturedImage.image] will be closed as soon as
+     * `onCaptureSuccess` is invoked. Otherwise, it will be the user's responsibility to close the
+     * images.
+     */
+    public val results: MutableList<CapturedImage> = mutableListOf()
     public val errors: MutableList<ImageCaptureException> = mutableListOf()
 
     override fun onCaptureSuccess(image: ImageProxy) {
         results.add(
-            ImageProperties(
-                size = Size(image.width, image.height),
-                format = image.format,
-                rotationDegrees = image.imageInfo.rotationDegrees,
-                cropRect = image.cropRect,
-                exif = getExif(image),
+            CapturedImage(
+                image = image,
+                properties =
+                    ImageProperties(
+                        size = Size(image.width, image.height),
+                        format = image.format,
+                        rotationDegrees = image.imageInfo.rotationDegrees,
+                        cropRect = image.cropRect,
+                        exif = getExif(image),
+                    )
             )
         )
-        image.close()
+        if (closeImageOnSuccess) {
+            image.close()
+        }
         latch.countDown()
     }
 
@@ -76,12 +101,12 @@
         return null
     }
 
-    public suspend fun awaitCaptures(timeout: Long = CAPTURE_TIMEOUT) {
+    public suspend fun awaitCaptures(timeout: Duration = CAPTURE_TIMEOUT) {
         Truth.assertThat(withTimeoutOrNull(timeout) { latch.await() }).isNotNull()
     }
 
     public suspend fun awaitCapturesAndAssert(
-        timeout: Long = CAPTURE_TIMEOUT,
+        timeout: Duration = CAPTURE_TIMEOUT,
         capturedImagesCount: Int = 0,
         errorsCount: Int = 0
     ) {
@@ -110,4 +135,8 @@
             deferredItems.forEach { it.await() }
         }
     }
+
+    public companion object {
+        private val CAPTURE_TIMEOUT = 15.seconds
+    }
 }
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeOnImageSavedCallback.kt b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeOnImageSavedCallback.kt
new file mode 100644
index 0000000..4ddec70
--- /dev/null
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeOnImageSavedCallback.kt
@@ -0,0 +1,85 @@
+/*
+ * 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.testing.impl.fakes
+
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.ImageCaptureException
+import com.google.common.truth.Truth
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.withTimeoutOrNull
+
+/**
+ * A fake implementation of the [ImageCapture.OnImageCapturedCallback] that is used for test.
+ *
+ * @param captureCount Number of captures to wait for.
+ */
+public class FakeOnImageSavedCallback(captureCount: Int = 1) : ImageCapture.OnImageSavedCallback {
+    private val latch = CountdownDeferred(captureCount)
+    public val results: MutableList<ImageCapture.OutputFileResults> = mutableListOf()
+    public val errors: MutableList<ImageCaptureException> = mutableListOf()
+
+    override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
+        results.add(outputFileResults)
+        latch.countDown()
+    }
+
+    override fun onError(exception: ImageCaptureException) {
+        errors.add(exception)
+        latch.countDown()
+    }
+
+    public suspend fun awaitCaptures(timeout: Duration = CAPTURE_TIMEOUT) {
+        Truth.assertThat(withTimeoutOrNull(timeout) { latch.await() }).isNotNull()
+    }
+
+    public suspend fun awaitCapturesAndAssert(
+        timeout: Duration = CAPTURE_TIMEOUT,
+        capturedImagesCount: Int = 0,
+        errorsCount: Int = 0
+    ) {
+        Truth.assertThat(withTimeoutOrNull(timeout) { latch.await() }).isNotNull()
+        Truth.assertThat(results.size).isEqualTo(capturedImagesCount)
+        Truth.assertThat(errors.size).isEqualTo(errorsCount)
+    }
+
+    private class CountdownDeferred(val count: Int) {
+
+        private val deferredItems =
+            mutableListOf<CompletableDeferred<Unit>>().apply {
+                repeat(count) { add(CompletableDeferred()) }
+            }
+        private var index = 0
+
+        fun countDown() {
+            if (index < count) {
+                deferredItems[index++].complete(Unit)
+            } else {
+                throw IllegalStateException("Countdown already finished")
+            }
+        }
+
+        suspend fun await() {
+            deferredItems.forEach { it.await() }
+        }
+    }
+
+    public companion object {
+        private val CAPTURE_TIMEOUT = 15.seconds
+    }
+}
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
index 346e8e9..4c1e375 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
@@ -84,8 +84,8 @@
 import androidx.camera.testing.impl.CoreAppTestUtil
 import androidx.camera.testing.impl.SurfaceTextureProvider
 import androidx.camera.testing.impl.WakelockEmptyActivityRule
-import androidx.camera.testing.impl.fakes.FakeImageCaptureCallback
 import androidx.camera.testing.impl.fakes.FakeLifecycleOwner
+import androidx.camera.testing.impl.fakes.FakeOnImageCapturedCallback
 import androidx.camera.testing.impl.fakes.FakeSessionProcessor
 import androidx.camera.testing.impl.mocks.MockScreenFlash
 import androidx.camera.video.Recorder
@@ -103,6 +103,8 @@
 import java.util.concurrent.TimeUnit
 import java.util.concurrent.atomic.AtomicInteger
 import kotlin.math.abs
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.Deferred
 import kotlinx.coroutines.Dispatchers
@@ -126,7 +128,7 @@
 private val BACK_SELECTOR = CameraSelector.DEFAULT_BACK_CAMERA
 private val FRONT_SELECTOR = CameraSelector.DEFAULT_FRONT_CAMERA
 private const val BACK_LENS_FACING = CameraSelector.LENS_FACING_BACK
-private const val CAPTURE_TIMEOUT = 15_000.toLong() //  15 seconds
+private val CAPTURE_TIMEOUT = 15.seconds
 private const val TOLERANCE = 1e-3f
 private val EXIF_GAINMAP_PATTERNS =
     listOf(
@@ -231,14 +233,14 @@
         }
 
         // Act.
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         useCase.takePicture(mainExecutor, callback)
 
         // Assert.
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         var sizeEnvelope = imageProperties.size
 
         // Some devices may not be able to fit the requested resolution. In this case, the returned
@@ -311,13 +313,13 @@
 
         if (camera.cameraInfo.isZslSupported) {
             val numImages = 5
-            val callback = FakeImageCaptureCallback(captureCount = numImages)
+            val callback = FakeOnImageCapturedCallback(captureCount = numImages)
             for (i in 0 until numImages) {
                 useCase.takePicture(mainExecutor, callback)
             }
 
             callback.awaitCapturesAndAssert(
-                timeout = numImages * CAPTURE_TIMEOUT,
+                timeout = CAPTURE_TIMEOUT.times(numImages),
                 capturedImagesCount = numImages
             )
         }
@@ -401,12 +403,12 @@
         }
 
         // Act.
-        val callback = FakeImageCaptureCallback(captureCount = numImages)
+        val callback = FakeOnImageCapturedCallback(captureCount = numImages)
         repeat(numImages) { useCase.takePicture(mainExecutor, callback) }
 
         // Assert.
         callback.awaitCapturesAndAssert(
-            timeout = numImages * CAPTURE_TIMEOUT,
+            timeout = CAPTURE_TIMEOUT.times(numImages),
             capturedImagesCount = numImages
         )
     }
@@ -463,7 +465,7 @@
         }
 
         // Act.
-        val callback = FakeImageCaptureCallback()
+        val callback = FakeOnImageCapturedCallback()
         imageCapture.takePicture(mainExecutor, callback)
 
         // Assert.
@@ -823,7 +825,7 @@
 
         // Wait for the signal that all the images have been saved.
         callback.awaitCapturesAndAssert(
-            timeout = numImages * CAPTURE_TIMEOUT,
+            timeout = CAPTURE_TIMEOUT.times(numImages),
             savedImagesCount = numImages
         )
     }
@@ -882,7 +884,7 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
 
         useCase.takePicture(mainExecutor, callback)
 
@@ -913,14 +915,14 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
 
         useCase.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         assertThat(imageProperties.format).isEqualTo(ImageFormat.RAW10)
     }
 
@@ -1037,13 +1039,13 @@
         // directly know  onStateAttached() callback has been received. Therefore, taking a
         // picture and waiting for the capture success callback to know the use case's
         // onStateAttached() callback has been received.
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         imageCapture.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val callback2 = FakeImageCaptureCallback(captureCount = 3)
+        val callback2 = FakeOnImageCapturedCallback(captureCount = 3)
         imageCapture.takePicture(mainExecutor, callback2)
         imageCapture.takePicture(mainExecutor, callback2)
         imageCapture.takePicture(mainExecutor, callback2)
@@ -1066,7 +1068,7 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, imageCapture)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 3)
+        val callback = FakeOnImageCapturedCallback(captureCount = 3)
         imageCapture.takePicture(mainExecutor, callback)
         imageCapture.takePicture(mainExecutor, callback)
         imageCapture.takePicture(mainExecutor, callback)
@@ -1094,7 +1096,7 @@
     @Test
     fun takePictureReturnsErrorNO_CAMERA_whenNotBound() = runBlocking {
         val imageCapture = ImageCapture.Builder().build()
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
 
         imageCapture.takePicture(mainExecutor, callback)
 
@@ -1243,7 +1245,7 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         useCase.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
@@ -1253,7 +1255,7 @@
         // same as original one.
         val expectedCroppingRatio = Rational(DEFAULT_RESOLUTION.width, DEFAULT_RESOLUTION.height)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         val cropRect = imageProperties.cropRect
 
         // Rotate the captured ImageProxy's crop rect into the coordinate space of the final
@@ -1280,7 +1282,7 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
 
         // Checks camera device sensor degrees to set target cropping aspect ratio match the
         // sensor orientation.
@@ -1298,7 +1300,7 @@
 
         // After target rotation is updated, the result cropping aspect ratio should still the
         // same as original one.
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         val cropRect = imageProperties.cropRect
 
         // Rotate the captured ImageProxy's crop rect into the coordinate space of the final
@@ -1353,7 +1355,7 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCaseGroup)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
 
         useCase.takePicture(mainExecutor, callback)
 
@@ -1362,7 +1364,7 @@
 
         // After target rotation is updated, the result cropping aspect ratio should still the
         // same as original one.
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         val cropRect = imageProperties.cropRect
 
         // Rotate the captured ImageProxy's crop rect into the coordinate space of the final
@@ -1447,13 +1449,13 @@
             cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         useCase.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         val cropRect = imageProperties.cropRect
         val cropRectAspectRatio = Rational(cropRect!!.height(), cropRect.width())
 
@@ -1610,13 +1612,13 @@
                 )
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         useCase.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
 
         // Check the output image rotation degrees value is correct.
         assertThat(imageProperties.rotationDegrees)
@@ -1683,13 +1685,13 @@
                 )
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         useCase.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         // Check the output image rotation degrees value is correct.
         assertThat(imageProperties.rotationDegrees)
             .isEqualTo(camera.cameraInfo.getSensorRotationDegrees(useCase.targetRotation))
@@ -1721,13 +1723,13 @@
                 )
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         useCase.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
 
         // Check the output image rotation degrees value is correct.
         assertThat(imageProperties.rotationDegrees)
@@ -1771,13 +1773,13 @@
                 )
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         imageCapture.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
 
         // Check the output image rotation degrees value is correct.
         assertThat(imageProperties.rotationDegrees)
@@ -1819,13 +1821,13 @@
             )
         }
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         imageCapture.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
 
         // Check the output image rotation degrees value is correct.
         if (isRotationOptionSupportedDevice()) {
@@ -1981,7 +1983,7 @@
             .isTrue()
 
         // Act.
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         withContext(Dispatchers.Main) {
             // Test the reproduce step in b/235119898
             cameraProvider.unbind(preview)
@@ -2008,7 +2010,7 @@
         }
 
         // wait for camera to start by taking a picture
-        val callback1 = FakeImageCaptureCallback(captureCount = 1)
+        val callback1 = FakeOnImageCapturedCallback(captureCount = 1)
         imageCapture.takePicture(mainExecutor, callback1)
         try {
             callback1.awaitCapturesAndAssert(capturedImagesCount = 1)
@@ -2017,7 +2019,7 @@
         }
 
         // Act.
-        val callback2 = FakeImageCaptureCallback(captureCount = 1)
+        val callback2 = FakeOnImageCapturedCallback(captureCount = 1)
         withContext(Dispatchers.Main) {
             cameraProvider.unbind(videoCapture)
             imageCapture.takePicture(mainExecutor, callback2)
@@ -2169,13 +2171,13 @@
 
         assertThat(imageCapture.resolutionInfo!!.resolution).isEqualTo(maxHighResolutionOutputSize)
 
-        val callback = FakeImageCaptureCallback(captureCount = 1)
+        val callback = FakeOnImageCapturedCallback(captureCount = 1)
         imageCapture.takePicture(mainExecutor, callback)
 
         // Wait for the signal that the image has been captured.
         callback.awaitCapturesAndAssert(capturedImagesCount = 1)
 
-        val imageProperties = callback.results.first()
+        val imageProperties = callback.results.first().properties
         assertThat(imageProperties.size).isEqualTo(maxHighResolutionOutputSize)
     }
 
@@ -2313,7 +2315,7 @@
         }
 
         suspend fun awaitCapturesAndAssert(
-            timeout: Long = CAPTURE_TIMEOUT,
+            timeout: Duration = CAPTURE_TIMEOUT,
             savedImagesCount: Int = 0,
             errorsCount: Int = 0
         ) {
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/fakecamera/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/fakecamera/ImageCaptureTest.kt
new file mode 100644
index 0000000..af52c44
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/fakecamera/ImageCaptureTest.kt
@@ -0,0 +1,239 @@
+/*
+ * 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.integration.core.fakecamera
+
+import android.content.ContentValues
+import android.content.Context
+import android.os.Build
+import android.provider.MediaStore
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.camera.testing.fakes.FakeAppConfig
+import androidx.camera.testing.fakes.FakeCamera
+import androidx.camera.testing.fakes.FakeCameraControl
+import androidx.camera.testing.impl.fakes.FakeLifecycleOwner
+import androidx.camera.testing.impl.fakes.FakeOnImageCapturedCallback
+import androidx.camera.testing.impl.fakes.FakeOnImageSavedCallback
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import org.junit.After
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Tests using a fake camera instead of real camera by replacing the camera-camera2 layer with
+ * camera-testing layer.
+ *
+ * They are aimed to ensure that integration between camera-core and camera-testing work seamlessly.
+ */
+@RunWith(Parameterized::class)
+class ImageCaptureTest(
+    @CameraSelector.LensFacing private val lensFacing: Int,
+) {
+    @get:Rule
+    val temporaryFolder =
+        TemporaryFolder(ApplicationProvider.getApplicationContext<Context>().cacheDir)
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+    private lateinit var cameraProvider: ProcessCameraProvider
+    private lateinit var camera: FakeCamera
+    private lateinit var cameraControl: FakeCameraControl
+    private lateinit var imageCapture: ImageCapture
+
+    @Before
+    fun setup() = runBlocking {
+        cameraProvider = getFakeConfigCameraProvider(context)
+        imageCapture = bindImageCapture()
+    }
+
+    @After
+    fun tearDown() = runBlocking {
+        if (::cameraProvider.isInitialized) {
+            withContext(Dispatchers.Main) { cameraProvider.shutdownAsync()[10, TimeUnit.SECONDS] }
+        }
+    }
+
+    // Duplicate to ImageCaptureTest on core-test-app JVM tests, any change here may need to be
+    // reflected there too
+    @Test
+    fun canSubmitTakePictureRequest(): Unit = runBlocking {
+        val countDownLatch = CountDownLatch(1)
+        cameraControl.setOnNewCaptureRequestListener { countDownLatch.countDown() }
+
+        imageCapture.takePicture(CameraXExecutors.directExecutor(), FakeOnImageCapturedCallback())
+
+        assertThat(countDownLatch.await(3, TimeUnit.SECONDS)).isTrue()
+    }
+
+    // Duplicate to ImageCaptureTest on core-test-app JVM tests, any change here may need to be
+    // reflected there too
+    @Ignore("b/318314454")
+    @Test
+    fun canCreateBitmapFromTakenImage_whenImageCapturedCallbackIsUsed(): Unit = runBlocking {
+        val callback = FakeOnImageCapturedCallback()
+        imageCapture.takePicture(CameraXExecutors.directExecutor(), callback)
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+        callback.results.first().image.toBitmap()
+    }
+
+    // Duplicate to ImageCaptureTest on core-test-app JVM tests, any change here may need to be
+    // reflected there too
+    @Ignore("b/318314454")
+    @Test
+    fun canFindImage_whenFileStorageAndImageSavedCallbackIsUsed(): Unit = runBlocking {
+        val saveLocation = temporaryFolder.newFile()
+        val previousLength = saveLocation.length()
+        val callback = FakeOnImageSavedCallback()
+
+        imageCapture.takePicture(
+            ImageCapture.OutputFileOptions.Builder(saveLocation).build(),
+            CameraXExecutors.directExecutor(),
+            callback
+        )
+
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+        assertThat(saveLocation.length()).isGreaterThan(previousLength)
+    }
+
+    // Duplicate to ImageCaptureTest on androidTest/fakecamera/ImageCaptureTest, any change here may
+    // need to be reflected there too
+    @Ignore("b/318314454")
+    @Test
+    fun canFindImage_whenMediaStoreAndImageSavedCallbackIsUsed(): Unit = runBlocking {
+        val initialCount = getMediaStoreCameraXImageCount()
+        val callback = FakeOnImageSavedCallback()
+        imageCapture.takePicture(
+            createMediaStoreOutputOptions(),
+            CameraXExecutors.directExecutor(),
+            callback
+        )
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+        assertThat(getMediaStoreCameraXImageCount()).isEqualTo(initialCount + 1)
+    }
+
+    private suspend fun bindImageCapture(): ImageCapture {
+        val imageCapture = ImageCapture.Builder().build()
+
+        withContext(Dispatchers.Main) {
+            cameraProvider.bindToLifecycle(
+                FakeLifecycleOwner().apply { startAndResume() },
+                CameraSelector.Builder().requireLensFacing(lensFacing).build(),
+                imageCapture
+            )
+        }
+
+        camera =
+            when (lensFacing) {
+                CameraSelector.LENS_FACING_BACK -> FakeAppConfig.getBackCamera()
+                CameraSelector.LENS_FACING_FRONT -> FakeAppConfig.getFrontCamera()
+                else -> throw AssertionError("Unsupported lens facing: $lensFacing")
+            }
+        cameraControl = camera.cameraControl as FakeCameraControl
+
+        return imageCapture
+    }
+
+    private fun getFakeConfigCameraProvider(context: Context): ProcessCameraProvider {
+        var cameraProvider: ProcessCameraProvider? = null
+        val latch = CountDownLatch(1)
+        ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+        ProcessCameraProvider.getInstance(context)
+            .addListener(
+                {
+                    cameraProvider = ProcessCameraProvider.getInstance(context).get()
+                    latch.countDown()
+                },
+                CameraXExecutors.directExecutor()
+            )
+
+        Truth.assertWithMessage("ProcessCameraProvider.getInstance timed out!")
+            .that(latch.await(5, TimeUnit.SECONDS))
+            .isTrue()
+
+        return cameraProvider!!
+    }
+
+    private fun createMediaStoreOutputOptions(): ImageCapture.OutputFileOptions {
+        // Create time stamped name and MediaStore entry.
+        val name =
+            FILENAME_PREFIX +
+                SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
+                    .format(System.currentTimeMillis())
+        val contentValues =
+            ContentValues().apply {
+                put(MediaStore.MediaColumns.DISPLAY_NAME, name)
+                put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
+                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
+                    put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
+                }
+            }
+
+        // Create output options object which contains file + metadata
+        return ImageCapture.OutputFileOptions.Builder(
+                context.contentResolver,
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                contentValues
+            )
+            .build()
+    }
+
+    private fun getMediaStoreCameraXImageCount(): Int {
+        val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME)
+        val selection = "${MediaStore.Images.Media.DISPLAY_NAME} LIKE ?"
+        val selectionArgs = arrayOf("$FILENAME_PREFIX%")
+
+        val query =
+            ApplicationProvider.getApplicationContext<Context>()
+                .contentResolver
+                .query(
+                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                    projection,
+                    selection,
+                    selectionArgs,
+                    null
+                )
+
+        return query?.use { cursor -> cursor.count } ?: 0
+    }
+
+    companion object {
+        private const val FILENAME_PREFIX = "cameraXPhoto"
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "LensFacing = {0}")
+        fun data() =
+            listOf(
+                arrayOf(CameraSelector.LENS_FACING_BACK),
+                arrayOf(CameraSelector.LENS_FACING_FRONT),
+            )
+    }
+}
diff --git a/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/ImageCaptureTest.kt
index b09987b..459187c 100644
--- a/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/ImageCaptureTest.kt
+++ b/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/ImageCaptureTest.kt
@@ -16,9 +16,10 @@
 
 package androidx.camera.integration.core
 
+import android.content.ContentValues
 import android.content.Context
 import android.os.Build
-import android.os.Looper
+import android.provider.MediaStore
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
@@ -27,13 +28,17 @@
 import androidx.camera.testing.fakes.FakeAppConfig
 import androidx.camera.testing.fakes.FakeCamera
 import androidx.camera.testing.fakes.FakeCameraControl
-import androidx.camera.testing.impl.fakes.FakeImageCaptureCallback
 import androidx.camera.testing.impl.fakes.FakeLifecycleOwner
+import androidx.camera.testing.impl.fakes.FakeOnImageCapturedCallback
+import androidx.camera.testing.impl.fakes.FakeOnImageSavedCallback
 import androidx.test.core.app.ApplicationProvider
 import androidx.testutils.MainDispatcherRule
 import com.google.common.truth.Truth.assertThat
+import java.text.SimpleDateFormat
+import java.util.Locale
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
@@ -42,9 +47,9 @@
 import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
+import org.junit.rules.TemporaryFolder
 import org.junit.runner.RunWith
 import org.robolectric.ParameterizedRobolectricTestRunner
-import org.robolectric.Shadows.shadowOf
 import org.robolectric.annotation.Config
 import org.robolectric.annotation.internal.DoNotInstrument
 
@@ -59,26 +64,20 @@
 
     @get:Rule val mainDispatcherRule = MainDispatcherRule(testDispatcher)
 
+    @get:Rule
+    val temporaryFolder =
+        TemporaryFolder(ApplicationProvider.getApplicationContext<Context>().cacheDir)
+
     private val context = ApplicationProvider.getApplicationContext<Context>()
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var camera: FakeCamera
     private lateinit var cameraControl: FakeCameraControl
     private lateinit var imageCapture: ImageCapture
 
-    companion object {
-        @JvmStatic
-        @ParameterizedRobolectricTestRunner.Parameters(name = "LensFacing = {0}")
-        fun data() =
-            listOf(
-                arrayOf(CameraSelector.LENS_FACING_BACK),
-                arrayOf(CameraSelector.LENS_FACING_FRONT),
-            )
-    }
-
     @Before
     fun setup() {
+        cameraProvider = getFakeConfigCameraProvider(context)
         imageCapture = bindImageCapture()
-        assertThat(imageCapture).isNotNull()
     }
 
     @After
@@ -88,28 +87,64 @@
         }
     }
 
+    // Duplicate to ImageCaptureTest on androidTest/fakecamera/ImageCaptureTest, any change here may
+    // need to be reflected there too
     @Test
     fun canSubmitTakePictureRequest(): Unit = runTest {
         val countDownLatch = CountDownLatch(1)
         cameraControl.setOnNewCaptureRequestListener { countDownLatch.countDown() }
 
-        imageCapture.takePicture(CameraXExecutors.directExecutor(), FakeImageCaptureCallback())
+        imageCapture.takePicture(CameraXExecutors.directExecutor(), FakeOnImageCapturedCallback())
 
         assertThat(countDownLatch.await(3, TimeUnit.SECONDS)).isTrue()
     }
 
-    @Ignore("TODO: b/318314454")
+    // Duplicate to ImageCaptureTest on androidTest/fakecamera/ImageCaptureTest, any change here may
+    // need to be reflected there too
+    @Ignore("b/318314454")
     @Test
-    fun canTakeImage(): Unit = runTest {
-        val callback = FakeImageCaptureCallback()
+    fun canCreateBitmapFromTakenImage_whenImageCapturedCallbackIsUsed(): Unit = runTest {
+        val callback = FakeOnImageCapturedCallback()
         imageCapture.takePicture(CameraXExecutors.directExecutor(), callback)
-        shadowOf(Looper.getMainLooper()).idle()
-        callback.awaitCaptures()
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+        callback.results.first().image.toBitmap()
+    }
+
+    // Duplicate to ImageCaptureTest on androidTest/fakecamera/ImageCaptureTest, any change here may
+    // need to be reflected there too
+    @Ignore("b/318314454")
+    @Test
+    fun canFindImage_whenFileStorageAndImageSavedCallbackIsUsed(): Unit = runTest {
+        val saveLocation = temporaryFolder.newFile()
+        val previousLength = saveLocation.length()
+        val callback = FakeOnImageSavedCallback()
+
+        imageCapture.takePicture(
+            ImageCapture.OutputFileOptions.Builder(saveLocation).build(),
+            CameraXExecutors.directExecutor(),
+            callback
+        )
+
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+        assertThat(saveLocation.length()).isGreaterThan(previousLength)
+    }
+
+    // Duplicate to ImageCaptureTest on androidTest/fakecamera/ImageCaptureTest, any change here may
+    // need to be reflected there too
+    @Ignore("b/318314454")
+    @Test
+    fun canFindFakeImageUri_whenMediaStoreAndImageSavedCallbackIsUsed(): Unit = runBlocking {
+        val callback = FakeOnImageSavedCallback()
+        imageCapture.takePicture(
+            createMediaStoreOutputOptions(),
+            CameraXExecutors.directExecutor(),
+            callback
+        )
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+        assertThat(callback.results.first().savedUri).isNotNull()
     }
 
     private fun bindImageCapture(): ImageCapture {
-        cameraProvider = getFakeConfigCameraProvider(context)
-
         val imageCapture = ImageCapture.Builder().build()
 
         cameraProvider.bindToLifecycle(
@@ -127,4 +162,40 @@
 
         return imageCapture
     }
+
+    private fun createMediaStoreOutputOptions(): ImageCapture.OutputFileOptions {
+        // Create time stamped name and MediaStore entry.
+        val name =
+            FILENAME_PREFIX +
+                SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
+                    .format(System.currentTimeMillis())
+        val contentValues =
+            ContentValues().apply {
+                put(MediaStore.MediaColumns.DISPLAY_NAME, name)
+                put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
+                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
+                    put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
+                }
+            }
+
+        // Create output options object which contains file + metadata
+        return ImageCapture.OutputFileOptions.Builder(
+                context.contentResolver,
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                contentValues
+            )
+            .build()
+    }
+
+    companion object {
+        private const val FILENAME_PREFIX = "cameraXPhoto"
+
+        @JvmStatic
+        @ParameterizedRobolectricTestRunner.Parameters(name = "LensFacing = {0}")
+        fun data() =
+            listOf(
+                arrayOf(CameraSelector.LENS_FACING_BACK),
+                arrayOf(CameraSelector.LENS_FACING_FRONT),
+            )
+    }
 }
diff --git a/collection/collection/build.gradle b/collection/collection/build.gradle
index 7833819..ff66423 100644
--- a/collection/collection/build.gradle
+++ b/collection/collection/build.gradle
@@ -53,7 +53,7 @@
         commonMain {
             dependencies {
                 api(libs.kotlinStdlib)
-                api(project(":annotation:annotation"))
+                api("androidx.annotation:annotation:1.9.0-alpha02")
             }
         }
 
diff --git a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimateBoundsTest.kt b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimateBoundsTest.kt
index 6159e8d..c69c971b 100644
--- a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimateBoundsTest.kt
+++ b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimateBoundsTest.kt
@@ -51,7 +51,6 @@
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.lerp
 import androidx.compose.ui.unit.round
 import androidx.compose.ui.util.fastRoundToInt
 import androidx.compose.ui.util.lerp
@@ -137,8 +136,9 @@
     @Test
     fun animateSize() =
         with(rule.density) {
+            val frameTime = 16 // milliseconds
             val frames = 14 // Even number to reliable test at half duration
-            val durationMillis = frames * 16
+            val durationMillis = frames * frameTime
             val rootSizePx = 400
             val boxSizeSmallPx = rootSizePx * 0.25f
             val boxSizeLargePx = rootSizePx * 0.5f
@@ -179,14 +179,14 @@
             rule.mainClock.autoAdvance = false
             isExpanded = true
             rule.waitForIdle()
-            rule.mainClock.advanceTimeByFrame()
-            rule.mainClock.advanceTimeByFrame()
 
-            // 1-frame latency. TODO: Can we fix this?
-            rule.mainClock.advanceTimeByFrame()
+            // Wait until first animated frame, for test stability
+            do {
+                rule.mainClock.advanceTimeByFrame()
+            } while (expectedSmallSize.round() == boxSize)
 
-            // Advance to approx. the middle of the animation
-            rule.mainClock.advanceTimeBy(durationMillis / 2L)
+            // Advance to approx. the middle of the animation (minus the first animated frame)
+            rule.mainClock.advanceTimeBy(durationMillis / 2L - frameTime)
 
             val expectedMidIntSize = (expectedLargeSize + expectedSmallSize).times(0.5f).round()
             assertEquals(expectedMidIntSize, boxSize)
@@ -501,6 +501,7 @@
             rule.mainClock.autoAdvance = false
 
             runBlocking { scrollState.scrollBy(itemSizePx) }
+            rule.waitForIdle()
 
             // Let animations play for the first frame
             rule.mainClock.advanceTimeByFrame()
@@ -519,17 +520,13 @@
             rule.waitForIdle()
             rule.mainClock.autoAdvance = false
 
-            // Not sure why, but we need to run this scroll within a runOnIdle to complete the test
-            // consistently across devices.
-            rule.runOnIdle {
-                runBlocking {
-                    // Scroll back into starting position
-                    scrollState.scrollBy(-itemSizePx)
-                }
+            runBlocking {
+                // Scroll back into starting position
+                scrollState.scrollBy(-itemSizePx)
             }
+            rule.waitForIdle()
 
             rule.mainClock.advanceTimeByFrame()
-            rule.mainClock.advanceTimeByFrame()
 
             // Position should correspond to the exaggerated keyframe offset.
             // Note that the keyframe is actually defined around the item's center
diff --git a/compose/material/material-navigation/build.gradle b/compose/material/material-navigation/build.gradle
index f577da2..4cf82b4 100644
--- a/compose/material/material-navigation/build.gradle
+++ b/compose/material/material-navigation/build.gradle
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -47,6 +49,7 @@
     description = "Compose Material integration with Navigation"
     legacyDisableKotlinStrictApiMode = true
     samples(projectOrArtifact(":compose:material:material-navigation-samples"))
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 android {
diff --git a/compose/material/material-navigation/samples/build.gradle b/compose/material/material-navigation/samples/build.gradle
index 20b3d14d..0e1cdc4 100644
--- a/compose/material/material-navigation/samples/build.gradle
+++ b/compose/material/material-navigation/samples/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -45,6 +47,7 @@
     mavenVersion = LibraryVersions.COMPOSE
     inceptionYear = "2024"
     description = "Samples for Compose Material integration with Navigation"
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 android {
diff --git a/compose/material3/adaptive/adaptive-layout/api/current.txt b/compose/material3/adaptive/adaptive-layout/api/current.txt
index 6a2ac8f..a64ea1b 100644
--- a/compose/material3/adaptive/adaptive-layout/api/current.txt
+++ b/compose/material3/adaptive/adaptive-layout/api/current.txt
@@ -41,8 +41,8 @@
   }
 
   public final class ListDetailPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
   }
 
   public final class ListDetailPaneScaffoldRole {
@@ -209,8 +209,8 @@
   }
 
   public final class SupportingPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
   }
 
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
@@ -223,6 +223,41 @@
     field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole INSTANCE;
   }
 
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneMotion {
+    ctor public ThreePaneMotion(androidx.compose.material3.adaptive.layout.PaneMotion primaryPaneMotion, androidx.compose.material3.adaptive.layout.PaneMotion secondaryPaneMotion, androidx.compose.material3.adaptive.layout.PaneMotion tertiaryPaneMotion, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> delayedPositionAnimationSpec);
+    method public androidx.compose.material3.adaptive.layout.ThreePaneMotion copy(optional androidx.compose.material3.adaptive.layout.PaneMotion primaryPaneMotion, optional androidx.compose.material3.adaptive.layout.PaneMotion secondaryPaneMotion, optional androidx.compose.material3.adaptive.layout.PaneMotion tertiaryPaneMotion, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> delayedPositionAnimationSpec);
+    method public operator androidx.compose.material3.adaptive.layout.PaneMotion get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getDelayedPositionAnimationSpec();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPositionAnimationSpec();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> getSizeAnimationSpec();
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> delayedPositionAnimationSpec;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec;
+    field public static final androidx.compose.material3.adaptive.layout.ThreePaneMotion.Companion Companion;
+  }
+
+  public static final class ThreePaneMotion.Companion {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneMotion getNoMotion();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneMotion NoMotion;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneMotionDefaults {
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPanePositionAnimationSpec();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPanePositionAnimationSpecDelayed();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> getPaneSizeAnimationSpec();
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> PanePositionAnimationSpec;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> PanePositionAnimationSpecDelayed;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> PaneSizeAnimationSpec;
+    field public static final androidx.compose.material3.adaptive.layout.ThreePaneMotionDefaults INSTANCE;
+  }
+
+  public final class ThreePaneMotionKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateListDetailPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateListDetailPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue targetScaffoldValue);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateSupportingPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateSupportingPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue targetScaffoldValue);
+  }
+
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
     ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy tertiaryPaneAdaptStrategy);
     method public operator androidx.compose.material3.adaptive.layout.AdaptStrategy get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
diff --git a/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt b/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
index 6a2ac8f..a64ea1b 100644
--- a/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
+++ b/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
@@ -41,8 +41,8 @@
   }
 
   public final class ListDetailPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
   }
 
   public final class ListDetailPaneScaffoldRole {
@@ -209,8 +209,8 @@
   }
 
   public final class SupportingPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
   }
 
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
@@ -223,6 +223,41 @@
     field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole INSTANCE;
   }
 
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneMotion {
+    ctor public ThreePaneMotion(androidx.compose.material3.adaptive.layout.PaneMotion primaryPaneMotion, androidx.compose.material3.adaptive.layout.PaneMotion secondaryPaneMotion, androidx.compose.material3.adaptive.layout.PaneMotion tertiaryPaneMotion, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> delayedPositionAnimationSpec);
+    method public androidx.compose.material3.adaptive.layout.ThreePaneMotion copy(optional androidx.compose.material3.adaptive.layout.PaneMotion primaryPaneMotion, optional androidx.compose.material3.adaptive.layout.PaneMotion secondaryPaneMotion, optional androidx.compose.material3.adaptive.layout.PaneMotion tertiaryPaneMotion, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec, optional androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> delayedPositionAnimationSpec);
+    method public operator androidx.compose.material3.adaptive.layout.PaneMotion get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getDelayedPositionAnimationSpec();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPositionAnimationSpec();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> getSizeAnimationSpec();
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> delayedPositionAnimationSpec;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec;
+    field public static final androidx.compose.material3.adaptive.layout.ThreePaneMotion.Companion Companion;
+  }
+
+  public static final class ThreePaneMotion.Companion {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneMotion getNoMotion();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneMotion NoMotion;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneMotionDefaults {
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPanePositionAnimationSpec();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPanePositionAnimationSpecDelayed();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> getPaneSizeAnimationSpec();
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> PanePositionAnimationSpec;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> PanePositionAnimationSpecDelayed;
+    property public final androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> PaneSizeAnimationSpec;
+    field public static final androidx.compose.material3.adaptive.layout.ThreePaneMotionDefaults INSTANCE;
+  }
+
+  public final class ThreePaneMotionKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateListDetailPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateListDetailPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue targetScaffoldValue);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateSupportingPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneMotion calculateSupportingPaneScaffoldMotion(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue targetScaffoldValue);
+  }
+
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
     ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy tertiaryPaneAdaptStrategy);
     method public operator androidx.compose.material3.adaptive.layout.AdaptStrategy get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt
index ea19285..2718a66 100644
--- a/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt
@@ -32,6 +32,7 @@
 @RunWith(JUnit4::class)
 class PaneScaffoldDirectiveTest {
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_compactWidth() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -46,6 +47,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_mediumWidth() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -60,6 +62,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_expandedWidth() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -74,6 +77,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_tabletop() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -88,6 +92,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_compactWidth() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -102,6 +107,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_mediumWidth() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -116,6 +122,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_expandedWidth() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -130,6 +137,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_tabletop() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -144,6 +152,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_alwaysAvoidHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -158,6 +167,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_avoidOccludingHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -172,6 +182,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_avoidSeparatingHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -186,6 +197,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateStandardPaneScaffoldDirective_neverAvoidHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirective(
@@ -200,6 +212,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_alwaysAvoidHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -214,6 +227,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_avoidOccludingHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -228,6 +242,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_avoidSeparatingHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
@@ -242,6 +257,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun test_calculateDensePaneScaffoldDirective_neverAvoidHinge() {
         val scaffoldDirective =
             calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
index 5bb4f4c..815399d 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
@@ -47,12 +47,12 @@
  * @param extraPane the extra pane of the scaffold, which is supposed to hold any supplementary info
  *   besides the list and the detail panes, for example, a task list or a mini-calendar view of a
  *   mail app. See [ListDetailPaneScaffoldRole.Extra].
- * @param paneExpansionDragHandle the pane expansion drag handle to let users be able to drag to
- *   change pane expansion state. Note that by default this argument will be `null`, and there won't
- *   be a drag handle rendered and users won't be able to drag to change the pane split. You can
- *   provide a [PaneExpansionDragHandle] here as our sample suggests. On the other hand, even if
- *   there's no drag handle, you can still modify [paneExpansionState] directly to apply pane
- *   expansion.
+ * @param paneMotions The specified motion of the panes. By default the value will be calculated by
+ *   [calculateListDetailPaneScaffoldMotion] according to the target [ThreePaneScaffoldValue].
+ * @param paneExpansionDragHandle provide a custom pane expansion drag handle to allow users to
+ *   resize panes and change the pane expansion state by dragging. This is `null` by default, which
+ *   renders no drag handle. Even there's no drag handle, you can still change pane size directly
+ *   via modifying [paneExpansionState].
  * @param paneExpansionState the state object of pane expansion.
  */
 @ExperimentalMaterial3AdaptiveApi
@@ -64,6 +64,7 @@
     detailPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
     modifier: Modifier = Modifier,
     extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
+    paneMotions: ThreePaneMotion = calculateListDetailPaneScaffoldMotion(value),
     paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
         null,
     paneExpansionState: PaneExpansionState = rememberPaneExpansionState(value),
@@ -73,6 +74,7 @@
         scaffoldDirective = directive,
         scaffoldValue = value,
         paneOrder = ListDetailPaneScaffoldDefaults.PaneOrder,
+        paneMotions = paneMotions,
         secondaryPane = listPane,
         tertiaryPane = extraPane,
         paneExpansionDragHandle = paneExpansionDragHandle,
@@ -102,6 +104,13 @@
  * @param extraPane the extra pane of the scaffold, which is supposed to hold any supplementary info
  *   besides the list and the detail panes, for example, a task list or a mini-calendar view of a
  *   mail app. See [ListDetailPaneScaffoldRole.Extra].
+ * @param paneMotions The specified motion of the panes. By default the value will be calculated by
+ *   [calculateListDetailPaneScaffoldMotion] according to the target [ThreePaneScaffoldValue].
+ * @param paneExpansionDragHandle provide a custom pane expansion drag handle to allow users to
+ *   resize panes and change the pane expansion state by dragging. This is `null` by default, which
+ *   renders no drag handle. Even there's no drag handle, you can still change pane size directly
+ *   via modifying [paneExpansionState].
+ * @param paneExpansionState the state object of pane expansion.
  */
 @ExperimentalMaterial3AdaptiveApi
 @Composable
@@ -112,14 +121,21 @@
     detailPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
     modifier: Modifier = Modifier,
     extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
+    paneMotions: ThreePaneMotion = scaffoldState.calculateListDetailPaneScaffoldMotion(),
+    paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
+        null,
+    paneExpansionState: PaneExpansionState = rememberPaneExpansionState(scaffoldState.targetState),
 ) {
     ThreePaneScaffold(
         modifier = modifier.fillMaxSize(),
         scaffoldDirective = directive,
         scaffoldState = scaffoldState,
         paneOrder = ListDetailPaneScaffoldDefaults.PaneOrder,
+        paneMotions = paneMotions,
         secondaryPane = listPane,
         tertiaryPane = extraPane,
+        paneExpansionDragHandle = paneExpansionDragHandle,
+        paneExpansionState = paneExpansionState,
         primaryPane = detailPane
     )
 }
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
index d0af5ed..a2a06c7 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("DEPRECATED") // Deprecated import WindowWidthSizeClass.
+
 package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
@@ -27,7 +29,6 @@
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.window.core.layout.WindowWidthSizeClass
 
 /**
  * Calculates the recommended [PaneScaffoldDirective] from a given [WindowAdaptiveInfo]. Use this
@@ -44,6 +45,7 @@
  * @return an [PaneScaffoldDirective] to be used to decide adaptive layout states.
  */
 @ExperimentalMaterial3AdaptiveApi
+@Suppress("DEPRECATION") // WindowWidthSizeClass is deprecated
 fun calculatePaneScaffoldDirective(
     windowAdaptiveInfo: WindowAdaptiveInfo,
     verticalHingePolicy: HingePolicy = HingePolicy.AvoidSeparating
@@ -51,11 +53,11 @@
     val maxHorizontalPartitions: Int
     val horizontalPartitionSpacerSize: Dp
     when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
-        WindowWidthSizeClass.COMPACT -> {
+        androidx.window.core.layout.WindowWidthSizeClass.COMPACT -> {
             maxHorizontalPartitions = 1
             horizontalPartitionSpacerSize = 0.dp
         }
-        WindowWidthSizeClass.MEDIUM -> {
+        androidx.window.core.layout.WindowWidthSizeClass.MEDIUM -> {
             maxHorizontalPartitions = 1
             horizontalPartitionSpacerSize = 0.dp
         }
@@ -108,12 +110,14 @@
  * @return an [PaneScaffoldDirective] to be used to decide adaptive layout states.
  */
 @ExperimentalMaterial3AdaptiveApi
+@Suppress("DEPRECATION") // WindowWidthSizeClass is deprecated
 fun calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(
     windowAdaptiveInfo: WindowAdaptiveInfo,
     verticalHingePolicy: HingePolicy = HingePolicy.AvoidSeparating
 ): PaneScaffoldDirective {
     val isMediumWidth =
-        windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.MEDIUM
+        windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass ==
+            androidx.window.core.layout.WindowWidthSizeClass.MEDIUM
     return with(calculatePaneScaffoldDirective(windowAdaptiveInfo, verticalHingePolicy)) {
         copy(
             maxHorizontalPartitions = if (isMediumWidth) 2 else maxHorizontalPartitions,
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
index 7b8abec..f828c05 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
@@ -41,12 +41,12 @@
  * @param extraPane the extra pane of the scaffold, which is supposed to hold any additional content
  *   besides the main and the supporting panes, for example, a styling panel in a doc app. See
  *   [SupportingPaneScaffoldRole.Extra].
- * @param paneExpansionDragHandle the pane expansion drag handle to let users be able to drag to
- *   change pane expansion state. Note that by default this argument will be `null`, and there won't
- *   be a drag handle rendered and users won't be able to drag to change the pane split. You can
- *   provide a [PaneExpansionDragHandle] here as our sample suggests. On the other hand, even if
- *   there's no drag handle, you can still modify [paneExpansionState] directly to apply pane
- *   expansion.
+ * @param paneMotions The specified motion of the panes. By default the value will be calculated by
+ *   [calculateSupportingPaneScaffoldMotion] according to the target [ThreePaneScaffoldValue].
+ * @param paneExpansionDragHandle provide a custom pane expansion drag handle to allow users to
+ *   resize panes and change the pane expansion state by dragging. This is `null` by default, which
+ *   renders no drag handle. Even there's no drag handle, you can still change pane size directly
+ *   via modifying [paneExpansionState].
  * @param paneExpansionState the state object of pane expansion.
  */
 @ExperimentalMaterial3AdaptiveApi
@@ -58,6 +58,7 @@
     supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
     modifier: Modifier = Modifier,
     extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
+    paneMotions: ThreePaneMotion = calculateSupportingPaneScaffoldMotion(value),
     paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
         null,
     paneExpansionState: PaneExpansionState = rememberPaneExpansionState(value),
@@ -69,6 +70,7 @@
         paneOrder = SupportingPaneScaffoldDefaults.PaneOrder,
         secondaryPane = supportingPane,
         tertiaryPane = extraPane,
+        paneMotions = paneMotions,
         paneExpansionDragHandle = paneExpansionDragHandle,
         paneExpansionState = paneExpansionState,
         primaryPane = mainPane
@@ -95,6 +97,13 @@
  * @param extraPane the extra pane of the scaffold, which is supposed to hold any additional content
  *   besides the main and the supporting panes, for example, a styling panel in a doc app. See
  *   [SupportingPaneScaffoldRole.Extra].
+ * @param paneMotions The specified motion of the panes. By default the value will be calculated by
+ *   [calculateSupportingPaneScaffoldMotion] according to the target [ThreePaneScaffoldValue].
+ * @param paneExpansionDragHandle provide a custom pane expansion drag handle to allow users to
+ *   resize panes and change the pane expansion state by dragging. This is `null` by default, which
+ *   renders no drag handle. Even there's no drag handle, you can still change pane size directly
+ *   via modifying [paneExpansionState].
+ * @param paneExpansionState the state object of pane expansion.
  */
 @ExperimentalMaterial3AdaptiveApi
 @Composable
@@ -105,6 +114,10 @@
     supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
     modifier: Modifier = Modifier,
     extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
+    paneMotions: ThreePaneMotion = scaffoldState.calculateSupportingPaneScaffoldMotion(),
+    paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
+        null,
+    paneExpansionState: PaneExpansionState = rememberPaneExpansionState(scaffoldState.targetState),
 ) {
     ThreePaneScaffold(
         modifier = modifier.fillMaxSize(),
@@ -113,6 +126,9 @@
         paneOrder = SupportingPaneScaffoldDefaults.PaneOrder,
         secondaryPane = supportingPane,
         tertiaryPane = extraPane,
+        paneMotions = paneMotions,
+        paneExpansionDragHandle = paneExpansionDragHandle,
+        paneExpansionState = paneExpansionState,
         primaryPane = mainPane
     )
 }
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotion.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotion.kt
index c3a54ac..23a9c59 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotion.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotion.kt
@@ -19,7 +19,6 @@
 import androidx.compose.animation.core.AnimationVector
 import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.animation.core.Spring
-import androidx.compose.animation.core.SpringSpec
 import androidx.compose.animation.core.TwoWayConverter
 import androidx.compose.animation.core.VectorizedFiniteAnimationSpec
 import androidx.compose.animation.core.VisibilityThreshold
@@ -33,6 +32,69 @@
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.util.fastForEachIndexed
 
+/**
+ * Calculates the default [ThreePaneMotion] of [ListDetailPaneScaffold] according to the given
+ * [ThreePaneScaffoldState]'s current and target values.
+ */
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+fun ThreePaneScaffoldState.calculateListDetailPaneScaffoldMotion(): ThreePaneMotion =
+    calculateThreePaneMotion(ListDetailPaneScaffoldDefaults.PaneOrder)
+
+/**
+ * Calculates the default [ThreePaneMotion] of [ListDetailPaneScaffold] according to the target and
+ * the previously remembered [ThreePaneScaffoldValue].
+ */
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+fun calculateListDetailPaneScaffoldMotion(
+    targetScaffoldValue: ThreePaneScaffoldValue
+): ThreePaneMotion =
+    calculateThreePaneMotion(targetScaffoldValue, ListDetailPaneScaffoldDefaults.PaneOrder)
+
+/**
+ * Calculates the default [ThreePaneMotion] of [SupportingPaneScaffold] according to the given
+ * [ThreePaneScaffoldState]'s current and target values.
+ */
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+fun ThreePaneScaffoldState.calculateSupportingPaneScaffoldMotion(): ThreePaneMotion =
+    calculateThreePaneMotion(SupportingPaneScaffoldDefaults.PaneOrder)
+
+/**
+ * Calculates the default [ThreePaneMotion] of [SupportingPaneScaffold] according to the target and
+ * the previously remembered [ThreePaneScaffoldValue].
+ */
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+fun calculateSupportingPaneScaffoldMotion(
+    targetScaffoldValue: ThreePaneScaffoldValue
+): ThreePaneMotion =
+    calculateThreePaneMotion(targetScaffoldValue, SupportingPaneScaffoldDefaults.PaneOrder)
+
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+internal fun ThreePaneScaffoldState.calculateThreePaneMotion(
+    paneOrder: ThreePaneScaffoldHorizontalOrder
+): ThreePaneMotion {
+    class ThreePaneMotionHolder(var value: ThreePaneMotion)
+
+    val resultHolder = remember { ThreePaneMotionHolder(ThreePaneMotion.NoMotion) }
+    if (currentState != targetState) {
+        // Only update motions when the state changes to prevent unnecessary recomposition at the
+        // end of state transitions.
+        val ltrPaneOrder = paneOrder.toLtrOrder(LocalLayoutDirection.current)
+        val paneMotions = calculatePaneMotion(currentState, targetState, ltrPaneOrder)
+        resultHolder.value =
+            ThreePaneMotion(
+                paneMotions[ltrPaneOrder.indexOf(ThreePaneScaffoldRole.Primary)],
+                paneMotions[ltrPaneOrder.indexOf(ThreePaneScaffoldRole.Secondary)],
+                paneMotions[ltrPaneOrder.indexOf(ThreePaneScaffoldRole.Tertiary)]
+            )
+    }
+    return resultHolder.value
+}
+
 @ExperimentalMaterial3AdaptiveApi
 @Composable
 internal fun calculateThreePaneMotion(
@@ -59,12 +121,28 @@
     return threePaneMotion
 }
 
+/**
+ * The class that provides motion settings for three pane scaffolds like [ListDetailPaneScaffold]
+ * and [SupportingPaneScaffold].
+ *
+ * @param primaryPaneMotion the specified [PaneMotion] of the primary pane, i.e.,
+ *   [ListDetailPaneScaffoldRole.Detail] or [SupportingPaneScaffoldRole.Main].
+ * @param secondaryPaneMotion the specified [PaneMotion] of the secondary pane, i.e.,
+ *   [ListDetailPaneScaffoldRole.List] or [SupportingPaneScaffoldRole.Supporting].
+ * @param tertiaryPaneMotion the specified [PaneMotion] of the tertiary pane, i.e.,
+ *   [ListDetailPaneScaffoldRole.Extra] or [SupportingPaneScaffoldRole.Extra].
+ * @param sizeAnimationSpec the specified [FiniteAnimationSpec] when animating pane size changes.
+ * @param positionAnimationSpec the specified [FiniteAnimationSpec] when animating pane position
+ *   changes.
+ * @param delayedPositionAnimationSpec the specified [FiniteAnimationSpec] when animating pane
+ *   position changes with a delay to emphasize entering panes.
+ */
 @ExperimentalMaterial3AdaptiveApi
 @Immutable
-internal class ThreePaneMotion(
-    val primaryPaneMotion: PaneMotion,
-    val secondaryPaneMotion: PaneMotion,
-    val tertiaryPaneMotion: PaneMotion,
+class ThreePaneMotion(
+    internal val primaryPaneMotion: PaneMotion,
+    internal val secondaryPaneMotion: PaneMotion,
+    internal val tertiaryPaneMotion: PaneMotion,
     val sizeAnimationSpec: FiniteAnimationSpec<IntSize> =
         ThreePaneMotionDefaults.PaneSizeAnimationSpec,
     val positionAnimationSpec: FiniteAnimationSpec<IntOffset> =
@@ -72,6 +150,22 @@
     val delayedPositionAnimationSpec: FiniteAnimationSpec<IntOffset> =
         ThreePaneMotionDefaults.PanePositionAnimationSpecDelayed
 ) {
+    /**
+     * Makes a copy of [ThreePaneMotion] with override values.
+     *
+     * @param primaryPaneMotion the specified [PaneMotion] of the primary pane, i.e.,
+     *   [ListDetailPaneScaffoldRole.Detail] or [SupportingPaneScaffoldRole.Main].
+     * @param secondaryPaneMotion the specified [PaneMotion] of the secondary pane, i.e.,
+     *   [ListDetailPaneScaffoldRole.List] or [SupportingPaneScaffoldRole.Supporting].
+     * @param tertiaryPaneMotion the specified [PaneMotion] of the tertiary pane, i.e.,
+     *   [ListDetailPaneScaffoldRole.Extra] or [SupportingPaneScaffoldRole.Extra].
+     * @param sizeAnimationSpec the specified [FiniteAnimationSpec] when animating pane size
+     *   changes.
+     * @param positionAnimationSpec the specified [FiniteAnimationSpec] when animating pane position
+     *   changes.
+     * @param delayedPositionAnimationSpec the specified [FiniteAnimationSpec] when animating pane
+     *   position changes with a delay to emphasize entering panes.
+     */
     fun copy(
         primaryPaneMotion: PaneMotion = this.primaryPaneMotion,
         secondaryPaneMotion: PaneMotion = this.secondaryPaneMotion,
@@ -90,6 +184,12 @@
             delayedPositionAnimationSpec
         )
 
+    /**
+     * Gets the specified [PaneMotion] of a given pane role.
+     *
+     * @param role the specified role of the pane, see [ListDetailPaneScaffoldRole] and
+     *   [SupportingPaneScaffoldRole].
+     */
     operator fun get(role: ThreePaneScaffoldRole): PaneMotion =
         when (role) {
             ThreePaneScaffoldRole.Primary -> primaryPaneMotion
@@ -131,6 +231,16 @@
 
     internal fun toPaneMotionList(ltrOrder: ThreePaneScaffoldHorizontalOrder): List<PaneMotion> =
         listOf(this[ltrOrder.firstPane], this[ltrOrder.secondPane], this[ltrOrder.thirdPane])
+
+    companion object {
+        /** A default [ThreePaneMotion] instance that specifies no motions. */
+        val NoMotion =
+            ThreePaneMotion(
+                DefaultPaneMotion.NoMotion,
+                DefaultPaneMotion.NoMotion,
+                DefaultPaneMotion.NoMotion
+            )
+    }
 }
 
 @OptIn(ExperimentalMaterial3AdaptiveApi::class)
@@ -250,18 +360,23 @@
     }
 }
 
+/** The default settings of three pane motions. */
 @ExperimentalMaterial3AdaptiveApi
-internal object ThreePaneMotionDefaults {
-    // TODO(conradchen): open this to public when we support motion customization
-    val PanePositionAnimationSpec: SpringSpec<IntOffset> =
+object ThreePaneMotionDefaults {
+    /** The default [FiniteAnimationSpec] of pane position animations. */
+    val PanePositionAnimationSpec: FiniteAnimationSpec<IntOffset> =
         spring(
             dampingRatio = 0.8f,
             stiffness = 600f,
             visibilityThreshold = IntOffset.VisibilityThreshold
         )
 
-    // TODO(conradchen): open this to public when we support motion customization
-    val PanePositionAnimationSpecDelayed: DelayedSpringSpec<IntOffset> =
+    /**
+     * The default [FiniteAnimationSpec] of pane position animations with a delay. It's by default
+     * used in the case when an enter pane will intersect with exit panes, we delay the entering
+     * animation to emphasize the entering transition.
+     */
+    val PanePositionAnimationSpecDelayed: FiniteAnimationSpec<IntOffset> =
         DelayedSpringSpec(
             dampingRatio = 0.8f,
             stiffness = 600f,
@@ -269,8 +384,8 @@
             visibilityThreshold = IntOffset.VisibilityThreshold
         )
 
-    // TODO(conradchen): open this to public when we support motion customization
-    val PaneSizeAnimationSpec: SpringSpec<IntSize> =
+    /** The default [FiniteAnimationSpec] of pane size animations. */
+    val PaneSizeAnimationSpec: FiniteAnimationSpec<IntSize> =
         spring(
             dampingRatio = 0.8f,
             stiffness = 600f,
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
index 62f8235..bebc466 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
@@ -65,6 +65,7 @@
  *   panes.
  * @param scaffoldValue The current adapted value of the scaffold.
  * @param paneOrder The horizontal order of the panes from start to end in the scaffold.
+ * @param paneMotions The specified motion of the panes.
  * @param secondaryPane The content of the secondary pane that has a priority lower then the primary
  *   pane but higher than the tertiary pane.
  * @param tertiaryPane The content of the tertiary pane that has the lowest priority.
@@ -110,7 +111,7 @@
     paneOrder: ThreePaneScaffoldHorizontalOrder,
     secondaryPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
     tertiaryPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
-    paneMotions: ThreePaneMotion = calculateThreePaneMotion(scaffoldState.targetState, paneOrder),
+    paneMotions: ThreePaneMotion = scaffoldState.calculateThreePaneMotion(paneOrder),
     paneExpansionState: PaneExpansionState = rememberPaneExpansionState(),
     paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
         null,
diff --git a/compose/material3/adaptive/adaptive-navigation/api/current.txt b/compose/material3/adaptive/adaptive-navigation/api/current.txt
index ac6ed05..4612aff 100644
--- a/compose/material3/adaptive/adaptive-navigation/api/current.txt
+++ b/compose/material3/adaptive/adaptive-navigation/api/current.txt
@@ -2,8 +2,8 @@
 package androidx.compose.material3.adaptive.navigation {
 
   public final class AndroidThreePaneScaffold_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableListDetailPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableSupportingPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableListDetailPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableSupportingPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
   }
 
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class BackNavigationBehavior {
diff --git a/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt b/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt
index ac6ed05..4612aff 100644
--- a/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt
+++ b/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt
@@ -2,8 +2,8 @@
 package androidx.compose.material3.adaptive.navigation {
 
   public final class AndroidThreePaneScaffold_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableListDetailPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableSupportingPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableListDetailPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableSupportingPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior, optional androidx.compose.material3.adaptive.layout.ThreePaneMotion paneMotions, optional kotlin.jvm.functions.Function2<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,? super androidx.compose.material3.adaptive.layout.PaneExpansionState,kotlin.Unit>? paneExpansionDragHandle, optional androidx.compose.material3.adaptive.layout.PaneExpansionState paneExpansionState);
   }
 
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class BackNavigationBehavior {
diff --git a/compose/material3/adaptive/adaptive-navigation/src/androidMain/kotlin/androidx/compose/material3/adaptive/navigation/AndroidThreePaneScaffold.android.kt b/compose/material3/adaptive/adaptive-navigation/src/androidMain/kotlin/androidx/compose/material3/adaptive/navigation/AndroidThreePaneScaffold.android.kt
index 48ba07a..859c8b8 100644
--- a/compose/material3/adaptive/adaptive-navigation/src/androidMain/kotlin/androidx/compose/material3/adaptive/navigation/AndroidThreePaneScaffold.android.kt
+++ b/compose/material3/adaptive/adaptive-navigation/src/androidMain/kotlin/androidx/compose/material3/adaptive/navigation/AndroidThreePaneScaffold.android.kt
@@ -22,8 +22,11 @@
 import androidx.compose.material3.adaptive.layout.PaneExpansionDragHandle
 import androidx.compose.material3.adaptive.layout.PaneExpansionState
 import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold as BaseSupportingPaneScaffold
+import androidx.compose.material3.adaptive.layout.ThreePaneMotion
 import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope
 import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope
+import androidx.compose.material3.adaptive.layout.calculateListDetailPaneScaffoldMotion
+import androidx.compose.material3.adaptive.layout.calculateSupportingPaneScaffoldMotion
 import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -45,6 +48,8 @@
  *   mail app. See [ListDetailPaneScaffoldRole.Extra].
  * @param defaultBackBehavior the default back navigation behavior when the system back event
  *   happens. See [BackNavigationBehavior] for the use cases of each behavior.
+ * @param paneMotions The specified motion of the panes. By default the value will be calculated by
+ *   [calculateListDetailPaneScaffoldMotion] according to the target [ThreePaneScaffoldValue].
  * @param paneExpansionDragHandle the pane expansion drag handle to let users be able to drag to
  *   change pane expansion state. Note that by default this argument will be `null`, and there won't
  *   be a drag handle rendered and users won't be able to drag to change the pane split. You can
@@ -62,6 +67,7 @@
     modifier: Modifier = Modifier,
     extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
     defaultBackBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilContentChange,
+    paneMotions: ThreePaneMotion = calculateListDetailPaneScaffoldMotion(navigator.scaffoldValue),
     paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
         null,
     paneExpansionState: PaneExpansionState = rememberPaneExpansionState(navigator.scaffoldValue),
@@ -77,6 +83,7 @@
         detailPane = detailPane,
         listPane = listPane,
         extraPane = extraPane,
+        paneMotions = paneMotions,
         paneExpansionDragHandle = paneExpansionDragHandle,
         paneExpansionState = paneExpansionState,
     )
@@ -98,6 +105,8 @@
  *   [SupportingPaneScaffoldRole.Extra].
  * @param defaultBackBehavior the default back navigation behavior when the system back event
  *   happens. See [BackNavigationBehavior] for the use cases of each behavior.
+ * @param paneMotions The specified motion of the panes. By default the value will be calculated by
+ *   [calculateSupportingPaneScaffoldMotion] according to the target [ThreePaneScaffoldValue].
  * @param paneExpansionDragHandle the pane expansion drag handle to let users be able to drag to
  *   change pane expansion state. Note that by default this argument will be `null`, and there won't
  *   be a drag handle rendered and users won't be able to drag to change the pane split. You can
@@ -115,6 +124,7 @@
     modifier: Modifier = Modifier,
     extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
     defaultBackBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilContentChange,
+    paneMotions: ThreePaneMotion = calculateSupportingPaneScaffoldMotion(navigator.scaffoldValue),
     paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? =
         null,
     paneExpansionState: PaneExpansionState = rememberPaneExpansionState(navigator.scaffoldValue),
@@ -130,6 +140,7 @@
         mainPane = mainPane,
         supportingPane = supportingPane,
         extraPane = extraPane,
+        paneMotions = paneMotions,
         paneExpansionDragHandle = paneExpansionDragHandle,
         paneExpansionState = paneExpansionState,
     )
diff --git a/compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt b/compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt
index 9781752..f47f656 100644
--- a/compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt
+++ b/compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt
@@ -33,6 +33,7 @@
 
 @OptIn(ExperimentalMaterial3AdaptiveApi::class)
 @Composable
+@Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
 actual fun currentWindowAdaptiveInfo(): WindowAdaptiveInfo {
     val windowSize = with(LocalDensity.current) { currentWindowSize().toSize().toDpSize() }
     return WindowAdaptiveInfo(
diff --git a/compose/material3/material3-adaptive-navigation-suite/samples/src/main/java/androidx/compose/material3/adaptive/navigationsuite/samples/NavigationSuiteScaffoldSamples.kt b/compose/material3/material3-adaptive-navigation-suite/samples/src/main/java/androidx/compose/material3/adaptive/navigationsuite/samples/NavigationSuiteScaffoldSamples.kt
index df28658..7d112c9 100644
--- a/compose/material3/material3-adaptive-navigation-suite/samples/src/main/java/androidx/compose/material3/adaptive/navigationsuite/samples/NavigationSuiteScaffoldSamples.kt
+++ b/compose/material3/material3-adaptive-navigation-suite/samples/src/main/java/androidx/compose/material3/adaptive/navigationsuite/samples/NavigationSuiteScaffoldSamples.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("DEPRECATION") // Suppress for WindowWidthSizeClass
+
 package androidx.compose.material3.adaptive.navigationsuite.samples
 
 import androidx.annotation.Sampled
@@ -76,6 +78,7 @@
 @Preview
 @Sampled
 @Composable
+@Suppress("DEPRECATION") // WindowWidthSizeClass is deprecated
 fun NavigationSuiteScaffoldCustomConfigSample() {
     var selectedItem by remember { mutableIntStateOf(0) }
     val navItems = listOf("Songs", "Artists", "Playlists")
diff --git a/compose/material3/material3-adaptive-navigation-suite/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffoldTest.kt b/compose/material3/material3-adaptive-navigation-suite/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffoldTest.kt
index 1eb9fa1..a68b7ddc 100644
--- a/compose/material3/material3-adaptive-navigation-suite/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffoldTest.kt
+++ b/compose/material3/material3-adaptive-navigation-suite/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffoldTest.kt
@@ -30,6 +30,7 @@
 class NavigationSuiteScaffoldTest {
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_compactWidth_compactHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(400f, 400f))
@@ -39,6 +40,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_compactWidth_mediumHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(400f, 800f))
@@ -48,6 +50,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_compactWidth_expandedHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(400f, 1000f))
@@ -57,6 +60,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_mediumWidth_compactHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(800f, 400f))
@@ -66,6 +70,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_mediumWidth_mediumHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(800f, 800f))
@@ -75,6 +80,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_mediumWidth_expandedHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(800f, 1000f))
@@ -84,6 +90,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_expandedWidth_compactHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(1000f, 400f))
@@ -93,6 +100,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_expandedWidth_mediumHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(1000f, 800f))
@@ -102,6 +110,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_expandedWidth_expandedHeight() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(windowSizeClass = WindowSizeClass.compute(1000f, 1000f))
@@ -111,6 +120,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_tableTop() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(
@@ -123,6 +133,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // WindowSizeClass#compute is deprecated
     fun navigationLayoutTypeTest_tableTop_expandedWidth() {
         val mockAdaptiveInfo =
             createMockAdaptiveInfo(
diff --git a/compose/material3/material3-adaptive-navigation-suite/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffold.kt b/compose/material3/material3-adaptive-navigation-suite/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffold.kt
index 5e96cd5..40758e0 100644
--- a/compose/material3/material3-adaptive-navigation-suite/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffold.kt
+++ b/compose/material3/material3-adaptive-navigation-suite/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigationsuite/NavigationSuiteScaffold.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("DEPRECATION") // Suppress for imports of WindowWidthSizeClass
+
 package androidx.compose.material3.adaptive.navigationsuite
 
 import androidx.compose.foundation.interaction.Interaction
@@ -407,6 +409,7 @@
      * @param adaptiveInfo the provided [WindowAdaptiveInfo]
      * @see NavigationSuiteScaffold
      */
+    @Suppress("DEPRECATION") // WindowWidthSizeClass deprecated
     fun calculateFromAdaptiveInfo(adaptiveInfo: WindowAdaptiveInfo): NavigationSuiteType {
         return with(adaptiveInfo) {
             if (
diff --git a/compose/ui/ui-geometry/api/current.txt b/compose/ui/ui-geometry/api/current.txt
index 9253299..7cfe3bd 100644
--- a/compose/ui/ui-geometry/api/current.txt
+++ b/compose/ui/ui-geometry/api/current.txt
@@ -94,12 +94,14 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class Offset {
+    ctor public Offset(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator float component1();
     method @androidx.compose.runtime.Stable public inline operator float component2();
     method public long copy(optional float x, optional float y);
     method @androidx.compose.runtime.Stable public operator long div(float operand);
     method @androidx.compose.runtime.Stable public float getDistance();
     method @androidx.compose.runtime.Stable public float getDistanceSquared();
+    method public long getPackedValue();
     method public inline float getX();
     method public inline float getY();
     method @androidx.compose.runtime.Stable public inline boolean isValid();
@@ -108,6 +110,7 @@
     method @androidx.compose.runtime.Stable public operator long rem(float operand);
     method @androidx.compose.runtime.Stable public operator long times(float operand);
     method @androidx.compose.runtime.Stable public inline operator long unaryMinus();
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final inline float x;
     property @androidx.compose.runtime.Stable public final inline float y;
     field public static final androidx.compose.ui.geometry.Offset.Companion Companion;
@@ -123,7 +126,7 @@
   }
 
   public final class OffsetKt {
-    method @androidx.compose.runtime.Stable public static long Offset(float x, float y);
+    method @androidx.compose.runtime.Stable public static inline long Offset(float x, float y);
     method public static inline boolean isFinite(long);
     method public static inline boolean isSpecified(long);
     method public static inline boolean isUnspecified(long);
@@ -267,6 +270,7 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class Size {
+    ctor public Size(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator float component1();
     method @androidx.compose.runtime.Stable public inline operator float component2();
     method public long copy(optional float width, optional float height);
@@ -274,12 +278,14 @@
     method public inline float getHeight();
     method public float getMaxDimension();
     method public float getMinDimension();
+    method public long getPackedValue();
     method public inline float getWidth();
     method @androidx.compose.runtime.Stable public boolean isEmpty();
     method @androidx.compose.runtime.Stable public operator long times(float operand);
     property @androidx.compose.runtime.Stable public final inline float height;
     property @androidx.compose.runtime.Stable public final float maxDimension;
     property @androidx.compose.runtime.Stable public final float minDimension;
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final inline float width;
     field public static final androidx.compose.ui.geometry.Size.Companion Companion;
   }
diff --git a/compose/ui/ui-geometry/api/restricted_current.txt b/compose/ui/ui-geometry/api/restricted_current.txt
index 4714d67..940e4ba 100644
--- a/compose/ui/ui-geometry/api/restricted_current.txt
+++ b/compose/ui/ui-geometry/api/restricted_current.txt
@@ -105,13 +105,14 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class Offset {
-    ctor @kotlin.PublishedApi internal Offset(@kotlin.PublishedApi long packedValue);
+    ctor public Offset(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator float component1();
     method @androidx.compose.runtime.Stable public inline operator float component2();
     method public long copy(optional float x, optional float y);
     method @androidx.compose.runtime.Stable public operator long div(float operand);
     method @androidx.compose.runtime.Stable public float getDistance();
     method @androidx.compose.runtime.Stable public float getDistanceSquared();
+    method public long getPackedValue();
     method public inline float getX();
     method public inline float getY();
     method @androidx.compose.runtime.Stable public inline boolean isValid();
@@ -120,6 +121,7 @@
     method @androidx.compose.runtime.Stable public operator long rem(float operand);
     method @androidx.compose.runtime.Stable public operator long times(float operand);
     method @androidx.compose.runtime.Stable public inline operator long unaryMinus();
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final inline float x;
     property @androidx.compose.runtime.Stable public final inline float y;
     field public static final androidx.compose.ui.geometry.Offset.Companion Companion;
@@ -135,7 +137,7 @@
   }
 
   public final class OffsetKt {
-    method @androidx.compose.runtime.Stable public static long Offset(float x, float y);
+    method @androidx.compose.runtime.Stable public static inline long Offset(float x, float y);
     method public static inline boolean isFinite(long);
     method public static inline boolean isSpecified(long);
     method public static inline boolean isUnspecified(long);
@@ -279,7 +281,7 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class Size {
-    ctor @kotlin.PublishedApi internal Size(@kotlin.PublishedApi long packedValue);
+    ctor public Size(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator float component1();
     method @androidx.compose.runtime.Stable public inline operator float component2();
     method public long copy(optional float width, optional float height);
@@ -287,12 +289,14 @@
     method public inline float getHeight();
     method public float getMaxDimension();
     method public float getMinDimension();
+    method public long getPackedValue();
     method public inline float getWidth();
     method @androidx.compose.runtime.Stable public boolean isEmpty();
     method @androidx.compose.runtime.Stable public operator long times(float operand);
     property @androidx.compose.runtime.Stable public final inline float height;
     property @androidx.compose.runtime.Stable public final float maxDimension;
     property @androidx.compose.runtime.Stable public final float minDimension;
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final inline float width;
     field public static final androidx.compose.ui.geometry.Size.Companion Companion;
   }
diff --git a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt
index 92ed64e..100212d 100644
--- a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt
+++ b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
+
 package androidx.compose.ui.geometry
 
 import androidx.compose.runtime.Immutable
@@ -24,8 +26,8 @@
 import androidx.compose.ui.util.unpackFloat2
 import kotlin.math.sqrt
 
-/** Constructs an Offset from the given relative x and y offsets */
-@Stable fun Offset(x: Float, y: Float) = Offset(packFloats(x, y))
+/** Constructs an Offset from the given relative [x] and [y] offsets */
+@Stable inline fun Offset(x: Float, y: Float) = Offset(packFloats(x, y))
 
 /**
  * An immutable 2D floating-point offset.
@@ -44,15 +46,20 @@
  * See also:
  * * [Size], which represents a vector describing the size of a rectangle.
  *
- * Creates an offset. The first argument sets [x], the horizontal component, and the second sets
- * [y], the vertical component.
+ * To create an [Offset], call the top-level function that accepts an x/y pair of coordinates:
+ * ```
+ * val offset = Offset(x, y)
+ * ```
+ *
+ * The primary constructor of [Offset] is intended to be used with the [packedValue] property to
+ * allow storing offsets in arrays or collections of primitives without boxing.
+ *
+ * @param packedValue [Long] value encoding the [x] and [y] components of the [Offset]. Encoded
+ *   values can be obtained by using the [packedValue] property of existing [Offset] instances.
  */
-@Suppress("NOTHING_TO_INLINE")
 @Immutable
 @kotlin.jvm.JvmInline
-value class Offset
-@PublishedApi
-internal constructor(@PublishedApi internal val packedValue: Long) {
+value class Offset(val packedValue: Long) {
     @Stable
     inline val x: Float
         get() = unpackFloat1(packedValue)
diff --git a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Size.kt b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Size.kt
index d47e8e4..e288fde 100644
--- a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Size.kt
+++ b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Size.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-@file:Suppress("NOTHING_TO_INLINE")
+@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
 
 package androidx.compose.ui.geometry
 
@@ -36,10 +36,22 @@
  * Holds a 2D floating-point size.
  *
  * You can think of this as an [Offset] from the origin.
+ *
+ * To create a [Size], call the top-level function that accepts a width/height pair of dimensions:
+ * ```
+ * val size = Size(width, height)
+ * ```
+ *
+ * The primary constructor of [Size] is intended to be used with the [packedValue] property to allow
+ * storing sizes in arrays or collections of primitives without boxing.
+ *
+ * @param packedValue [Long] value encoding the [width] and [height] components of the [Size].
+ *   Encoded values can be obtained by using the [packedValue] property of existing [Size]
+ *   instances.
  */
 @Immutable
 @kotlin.jvm.JvmInline
-value class Size @PublishedApi internal constructor(@PublishedApi internal val packedValue: Long) {
+value class Size(val packedValue: Long) {
     @Stable
     inline val width: Float
         get() = unpackFloat1(packedValue)
@@ -57,7 +69,6 @@
         Size(packFloats(width, height))
 
     companion object {
-
         /** An empty size, one with a zero width and a zero height. */
         @Stable val Zero = Size(0x0L)
 
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/AccessibilityChecksTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/AccessibilityChecksTest.kt
index 30b464c..e1b9966 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/AccessibilityChecksTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/AccessibilityChecksTest.kt
@@ -111,7 +111,7 @@
     @Composable
     private fun BoxWithMissingContentDescription() {
         Box(
-            Modifier.size(48.dp).semantics {
+            Modifier.size(20.dp).semantics {
                 // The SemanticsModifier will make this node importantForAccessibility
                 // Having no content description is now a violation
                 this.contentDescription = ""
diff --git a/compose/ui/ui-unit/api/current.txt b/compose/ui/ui-unit/api/current.txt
index 08d8d65..c372803 100644
--- a/compose/ui/ui-unit/api/current.txt
+++ b/compose/ui/ui-unit/api/current.txt
@@ -94,7 +94,7 @@
   }
 
   public final class DpKt {
-    method @androidx.compose.runtime.Stable public static long DpOffset(float x, float y);
+    method @androidx.compose.runtime.Stable public static inline long DpOffset(float x, float y);
     method @androidx.compose.runtime.Stable public static long DpSize(float width, float height);
     method @androidx.compose.runtime.Stable public static inline float coerceAtLeast(float, float minimumValue);
     method @androidx.compose.runtime.Stable public static inline float coerceAtMost(float, float maximumValue);
@@ -129,11 +129,14 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class DpOffset {
+    ctor public DpOffset(long packedValue);
     method public long copy(optional float x, optional float y);
+    method public long getPackedValue();
     method public float getX();
     method public float getY();
     method @androidx.compose.runtime.Stable public operator long minus(long other);
     method @androidx.compose.runtime.Stable public operator long plus(long other);
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final float x;
     property @androidx.compose.runtime.Stable public final float y;
     field public static final androidx.compose.ui.unit.DpOffset.Companion Companion;
@@ -203,10 +206,12 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class IntOffset {
+    ctor public IntOffset(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator int component1();
     method @androidx.compose.runtime.Stable public inline operator int component2();
     method public long copy(optional int x, optional int y);
     method @androidx.compose.runtime.Stable public operator long div(float operand);
+    method public long getPackedValue();
     method public int getX();
     method public int getY();
     method @androidx.compose.runtime.Stable public operator long minus(long other);
@@ -214,6 +219,7 @@
     method @androidx.compose.runtime.Stable public operator long rem(int operand);
     method @androidx.compose.runtime.Stable public operator long times(float operand);
     method @androidx.compose.runtime.Stable public operator long unaryMinus();
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final int x;
     property @androidx.compose.runtime.Stable public final int y;
     field public static final androidx.compose.ui.unit.IntOffset.Companion Companion;
@@ -225,7 +231,7 @@
   }
 
   public final class IntOffsetKt {
-    method @androidx.compose.runtime.Stable public static long IntOffset(int x, int y);
+    method @androidx.compose.runtime.Stable public static inline long IntOffset(int x, int y);
     method @androidx.compose.runtime.Stable public static long lerp(long start, long stop, float fraction);
     method @androidx.compose.runtime.Stable public static operator long minus(long, long offset);
     method @androidx.compose.runtime.Stable public static operator long minus(long, long offset);
@@ -309,9 +315,11 @@
     method @androidx.compose.runtime.Stable public inline operator int component2();
     method @androidx.compose.runtime.Stable public operator long div(int other);
     method public inline int getHeight();
+    method public long getPackedValue();
     method public inline int getWidth();
     method @androidx.compose.runtime.Stable public operator long times(int other);
     property @androidx.compose.runtime.Stable public final inline int height;
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final inline int width;
     field public static final androidx.compose.ui.unit.IntSize.Companion Companion;
   }
diff --git a/compose/ui/ui-unit/api/restricted_current.txt b/compose/ui/ui-unit/api/restricted_current.txt
index 8732633..6f13e9f 100644
--- a/compose/ui/ui-unit/api/restricted_current.txt
+++ b/compose/ui/ui-unit/api/restricted_current.txt
@@ -94,7 +94,7 @@
   }
 
   public final class DpKt {
-    method @androidx.compose.runtime.Stable public static long DpOffset(float x, float y);
+    method @androidx.compose.runtime.Stable public static inline long DpOffset(float x, float y);
     method @androidx.compose.runtime.Stable public static long DpSize(float width, float height);
     method @androidx.compose.runtime.Stable public static inline float coerceAtLeast(float, float minimumValue);
     method @androidx.compose.runtime.Stable public static inline float coerceAtMost(float, float maximumValue);
@@ -129,11 +129,14 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class DpOffset {
+    ctor public DpOffset(long packedValue);
     method public long copy(optional float x, optional float y);
+    method public long getPackedValue();
     method public float getX();
     method public float getY();
     method @androidx.compose.runtime.Stable public operator long minus(long other);
     method @androidx.compose.runtime.Stable public operator long plus(long other);
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final float x;
     property @androidx.compose.runtime.Stable public final float y;
     field public static final androidx.compose.ui.unit.DpOffset.Companion Companion;
@@ -203,10 +206,12 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class IntOffset {
+    ctor public IntOffset(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator int component1();
     method @androidx.compose.runtime.Stable public inline operator int component2();
     method public long copy(optional int x, optional int y);
     method @androidx.compose.runtime.Stable public operator long div(float operand);
+    method public long getPackedValue();
     method public int getX();
     method public int getY();
     method @androidx.compose.runtime.Stable public operator long minus(long other);
@@ -214,6 +219,7 @@
     method @androidx.compose.runtime.Stable public operator long rem(int operand);
     method @androidx.compose.runtime.Stable public operator long times(float operand);
     method @androidx.compose.runtime.Stable public operator long unaryMinus();
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final int x;
     property @androidx.compose.runtime.Stable public final int y;
     field public static final androidx.compose.ui.unit.IntOffset.Companion Companion;
@@ -225,7 +231,7 @@
   }
 
   public final class IntOffsetKt {
-    method @androidx.compose.runtime.Stable public static long IntOffset(int x, int y);
+    method @androidx.compose.runtime.Stable public static inline long IntOffset(int x, int y);
     method @androidx.compose.runtime.Stable public static long lerp(long start, long stop, float fraction);
     method @androidx.compose.runtime.Stable public static operator long minus(long, long offset);
     method @androidx.compose.runtime.Stable public static operator long minus(long, long offset);
@@ -305,14 +311,16 @@
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class IntSize {
-    ctor @kotlin.PublishedApi internal IntSize(@kotlin.PublishedApi long packedValue);
+    ctor @kotlin.PublishedApi internal IntSize(long packedValue);
     method @androidx.compose.runtime.Stable public inline operator int component1();
     method @androidx.compose.runtime.Stable public inline operator int component2();
     method @androidx.compose.runtime.Stable public operator long div(int other);
     method public inline int getHeight();
+    method public long getPackedValue();
     method public inline int getWidth();
     method @androidx.compose.runtime.Stable public operator long times(int other);
     property @androidx.compose.runtime.Stable public final inline int height;
+    property public final long packedValue;
     property @androidx.compose.runtime.Stable public final inline int width;
     field public static final androidx.compose.ui.unit.IntSize.Companion Companion;
   }
diff --git a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Dp.kt b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Dp.kt
index 4cc9af8..45a4b6d 100644
--- a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Dp.kt
+++ b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Dp.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@file:Suppress("NOTHING_TO_INLINE")
+@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
 
 package androidx.compose.ui.unit
 
@@ -181,12 +181,25 @@
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 /** Constructs a [DpOffset] from [x] and [y] position [Dp] values. */
-@Stable fun DpOffset(x: Dp, y: Dp): DpOffset = DpOffset(packFloats(x.value, y.value))
+@Stable inline fun DpOffset(x: Dp, y: Dp): DpOffset = DpOffset(packFloats(x.value, y.value))
 
-/** A two-dimensional offset using [Dp] for units */
+/**
+ * A two-dimensional offset using [Dp] for units.
+ *
+ * To create a [DpOffset], call the top-level function that accepts an x/y pair of coordinates:
+ * ```
+ * val offset = DpOffset(x, y)
+ * ```
+ *
+ * The primary constructor of [DpOffset] is intended to be used with the [packedValue] property to
+ * allow storing offsets in arrays or collections of primitives without boxing.
+ *
+ * @param packedValue [Long] value encoding the [x] and [y] components of the [DpOffset]. Encoded
+ *   values can be obtained by using the [packedValue] property of existing [DpOffset] instances.
+ */
 @Immutable
 @JvmInline
-value class DpOffset internal constructor(@PublishedApi internal val packedValue: Long) {
+value class DpOffset(val packedValue: Long) {
     /** The horizontal aspect of the offset in [Dp] */
     @Stable
     val x: Dp
diff --git a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntOffset.kt b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntOffset.kt
index 9bafe44..ca4caa3 100644
--- a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntOffset.kt
+++ b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntOffset.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-@file:Suppress("NOTHING_TO_INLINE")
+@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
 
 package androidx.compose.ui.unit
 
@@ -29,12 +29,25 @@
 import kotlin.jvm.JvmInline
 
 /** Constructs a [IntOffset] from [x] and [y] position [Int] values. */
-@Stable fun IntOffset(x: Int, y: Int): IntOffset = IntOffset(packInts(x, y))
+@Stable inline fun IntOffset(x: Int, y: Int): IntOffset = IntOffset(packInts(x, y))
 
-/** A two-dimensional position using [Int] pixels for units */
+/**
+ * A two-dimensional position using [Int] pixels for units.
+ *
+ * To create an [IntOffset], call the top-level function that accepts an x/y pair of coordinates:
+ * ```
+ * val offset = IntOffset(x, y)
+ * ```
+ *
+ * The primary constructor of [IntOffset] is intended to be used with the [packedValue] property to
+ * allow storing offsets in arrays or collections of primitives without boxing.
+ *
+ * @param packedValue [Long] value encoding the [x] and [y] components of the [IntOffset]. Encoded
+ *   values can be obtained by using the [packedValue] property of existing [IntOffset] instances.
+ */
 @Immutable
 @JvmInline
-value class IntOffset internal constructor(@PublishedApi internal val packedValue: Long) {
+value class IntOffset(val packedValue: Long) {
     /** The horizontal aspect of the position in [Int] pixels. */
     @Stable
     val x: Int
diff --git a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntSize.kt b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntSize.kt
index 48c1d7d..021b42d 100644
--- a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntSize.kt
+++ b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/IntSize.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-@file:Suppress("NOTHING_TO_INLINE")
+@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
 
 package androidx.compose.ui.unit
 
@@ -29,12 +29,25 @@
 /** Constructs an [IntSize] from width and height [Int] values. */
 @Stable inline fun IntSize(width: Int, height: Int): IntSize = IntSize(packInts(width, height))
 
-/** A two-dimensional size class used for measuring in [Int] pixels. */
+/**
+ * A two-dimensional size class used for measuring in [Int] pixels.
+ *
+ * To create an [IntSize], call the top-level function that accepts a width/height pair of
+ * dimensions:
+ * ```
+ * val size = IntSize(width, height)
+ * ```
+ *
+ * The primary constructor of [IntSize] is intended to be used with the [packedValue] property to
+ * allow storing sizes in arrays or collections of primitives without boxing.
+ *
+ * @param packedValue [Long] value encoding the [width] and [height] components of the [IntSize].
+ *   Encoded values can be obtained by using the [packedValue] property of existing [IntSize]
+ *   instances.
+ */
 @Immutable
 @kotlin.jvm.JvmInline
-value class IntSize
-@PublishedApi
-internal constructor(@PublishedApi internal val packedValue: Long) {
+value class IntSize @PublishedApi internal constructor(val packedValue: Long) {
     /** The horizontal aspect of the size in [Int] pixels. */
     @Stable
     inline val width: Int
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogTest.kt
index 5906b9f..5abbb34 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogTest.kt
@@ -15,11 +15,8 @@
  */
 package androidx.compose.ui.window
 
-import android.util.DisplayMetrics
+import android.content.res.Configuration
 import android.view.KeyEvent
-import android.view.MotionEvent.ACTION_DOWN
-import android.view.MotionEvent.ACTION_UP
-import android.view.View
 import androidx.activity.OnBackPressedDispatcher
 import androidx.activity.compose.BackHandler
 import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
@@ -38,11 +35,8 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.geometry.lerp
-import androidx.compose.ui.gesture.MotionEvent
-import androidx.compose.ui.gesture.PointerProperties
-import androidx.compose.ui.input.pointer.PointerCoords
 import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.SemanticsNodeInteraction
 import androidx.compose.ui.test.assertIsDisplayed
@@ -265,9 +259,9 @@
     fun canFillScreenWidth_dependingOnProperty() {
         var box1Width = 0
         var box2Width = 0
-        lateinit var displayMetrics: DisplayMetrics
+        lateinit var configuration: Configuration
         rule.setContent {
-            displayMetrics = LocalView.current.context.resources.displayMetrics
+            configuration = LocalConfiguration.current
             Dialog(
                 onDismissRequest = {},
                 properties = DialogProperties(usePlatformDefaultWidth = false)
@@ -278,7 +272,7 @@
                 Box(Modifier.fillMaxSize().onSizeChanged { box2Width = it.width })
             }
         }
-        val expectedWidth = with(rule.density) { displayMetrics.widthPixels }
+        val expectedWidth = with(rule.density) { configuration.screenWidthDp.dp.roundToPx() }
         assertThat(box1Width).isEqualTo(expectedWidth)
         assertThat(box2Width).isLessThan(box1Width)
     }
@@ -319,75 +313,6 @@
         }
     }
 
-    @Test
-    fun dismissWhenClickingOutsideContent() {
-        var dismissed = false
-        var clicked = false
-        lateinit var composeView: View
-        val clickBoxTag = "clickBox"
-        rule.setContent {
-            Dialog(
-                onDismissRequest = { dismissed = true },
-                properties =
-                    DialogProperties(
-                        usePlatformDefaultWidth = false,
-                        decorFitsSystemWindows = false
-                    )
-            ) {
-                composeView = LocalView.current
-                Box(Modifier.size(10.dp).testTag(clickBoxTag).clickable { clicked = true })
-            }
-        }
-
-        // click inside the compose view
-        rule.onNodeWithTag(clickBoxTag).performClick()
-
-        rule.waitForIdle()
-
-        assertThat(dismissed).isFalse()
-        assertThat(clicked).isTrue()
-
-        clicked = false
-
-        // click outside the compose view
-        rule.waitForIdle()
-        var root = composeView
-        while (root.parent is View) {
-            root = root.parent as View
-        }
-
-        rule.runOnIdle {
-            val x = root.width / 4f
-            val y = root.height / 4f
-            val down =
-                MotionEvent(
-                    eventTime = 0,
-                    action = ACTION_DOWN,
-                    numPointers = 1,
-                    actionIndex = 0,
-                    pointerProperties = arrayOf(PointerProperties(0)),
-                    pointerCoords = arrayOf(PointerCoords(x, y)),
-                    root
-                )
-            root.dispatchTouchEvent(down)
-            val up =
-                MotionEvent(
-                    eventTime = 10,
-                    action = ACTION_UP,
-                    numPointers = 1,
-                    actionIndex = 0,
-                    pointerProperties = arrayOf(PointerProperties(0)),
-                    pointerCoords = arrayOf(PointerCoords(x, y)),
-                    root
-                )
-            root.dispatchTouchEvent(up)
-        }
-        rule.waitForIdle()
-
-        assertThat(dismissed).isTrue()
-        assertThat(clicked).isFalse()
-    }
-
     private fun setupDialogTest(
         closeDialogOnDismiss: Boolean = true,
         dialogProperties: DialogProperties = DialogProperties(),
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogWithInsetsTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogWithInsetsTest.kt
index cde57e5..e85b14c 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogWithInsetsTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/DialogWithInsetsTest.kt
@@ -15,16 +15,12 @@
  */
 package androidx.compose.ui.window
 
-import android.content.res.Configuration
-import android.os.Build
 import android.view.View
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.WindowInsets
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.ime
 import androidx.compose.foundation.layout.imePadding
-import androidx.compose.foundation.layout.safeDrawing
-import androidx.compose.foundation.layout.safeDrawingPadding
 import androidx.compose.material.TextField
 import androidx.compose.runtime.SideEffect
 import androidx.compose.ui.Alignment
@@ -33,18 +29,10 @@
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.layout
-import androidx.compose.ui.layout.onPlaced
 import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.layout.positionInRoot
 import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.platform.SoftwareKeyboardController
-import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.requestFocus
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.core.graphics.Insets
@@ -53,10 +41,8 @@
 import androidx.core.view.WindowInsetsControllerCompat
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
-import kotlin.math.roundToInt
 import org.junit.Assert.assertNotEquals
 import org.junit.Rule
 import org.junit.Test
@@ -143,90 +129,6 @@
         assertNotEquals(Insets.NONE, imeInsets)
     }
 
-    @Test
-    fun dialogCanTakeEntireScreen() {
-        var size = IntSize.Zero
-        var displayWidth = 0
-        var displayHeight = 0
-        var insetsLeft = 0
-        var insetsTop = 0
-        var insetsRight = 0
-        var insetsBottom = 0
-        var textTop = 0
-        var controller: SoftwareKeyboardController? = null
-        rule.setContent {
-            val displayMetrics = LocalView.current.resources.displayMetrics
-            controller = LocalSoftwareKeyboardController.current
-            displayWidth = displayMetrics.widthPixels
-            displayHeight = displayMetrics.heightPixels
-            Box(Modifier.fillMaxSize()) {
-                Dialog(
-                    {},
-                    properties =
-                        DialogProperties(
-                            decorFitsSystemWindows = false,
-                            usePlatformDefaultWidth = false
-                        )
-                ) {
-                    val insets = WindowInsets.safeDrawing
-
-                    Box(
-                        Modifier.fillMaxSize()
-                            .layout { m, c ->
-                                val p = m.measure(c)
-                                size = IntSize(p.width, p.height)
-                                insetsTop = insets.getTop(this)
-                                insetsLeft = insets.getLeft(this, layoutDirection)
-                                insetsBottom = insets.getBottom(this)
-                                insetsRight = insets.getRight(this, layoutDirection)
-                                layout(p.width, p.height) { p.place(0, 0) }
-                            }
-                            .safeDrawingPadding()
-                    ) {
-                        TextField(
-                            value = "Hello",
-                            onValueChange = {},
-                            Modifier.align(Alignment.BottomStart).testTag("textField").onPlaced {
-                                layoutCoordinates ->
-                                textTop = layoutCoordinates.positionInRoot().y.roundToInt()
-                            }
-                        )
-                    }
-                }
-            }
-        }
-        rule.waitForIdle()
-
-        if (
-            Build.VERSION.SDK_INT >= 35 &&
-                rule.activity.applicationContext.applicationInfo.targetSdkVersion >= 35
-        ) {
-            // On SDK >= 35, the metrics is the size of the entire screen
-            assertThat(size.width).isEqualTo(displayWidth)
-            assertThat(size.height).isEqualTo(displayHeight)
-        } else {
-            // On SDK < 35, the metrics is the size of the screen with some insets removed
-            assertThat(size.width).isAtLeast(displayWidth)
-            assertThat(size.height).isAtLeast(displayHeight)
-        }
-        // There is going to be some insets
-        assertThat(maxOf(insetsLeft, insetsTop, insetsRight, insetsBottom)).isNotEqualTo(0)
-
-        val hardKeyboardHidden =
-            rule.runOnUiThread { rule.activity.resources.configuration.hardKeyboardHidden }
-        if (hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
-            return // can't launch the IME when the hardware keyboard is up.
-        }
-        val bottomInsetsBeforeIme = insetsBottom
-        val textTopBeforeIme = textTop
-        rule.onNodeWithTag("textField").requestFocus()
-        rule.waitUntil {
-            controller?.show()
-            insetsBottom != bottomInsetsBeforeIme
-        }
-        rule.runOnIdle { assertThat(textTop).isLessThan(textTopBeforeIme) }
-    }
-
     private fun findDialogWindowProviderInParent(view: View): DialogWindowProvider? {
         if (view is DialogWindowProvider) {
             return view
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 6fa2b45..72202ff 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
@@ -268,7 +268,7 @@
     // flaky, so we use this callback to test accessibility events.
     @VisibleForTesting
     internal var onSendAccessibilityEvent: (AccessibilityEvent) -> Boolean = {
-        trace("sendAccessibilityEvent") { view.parent.requestSendAccessibilityEvent(view, it) }
+        view.parent.requestSendAccessibilityEvent(view, it)
     }
 
     private val accessibilityManager: AccessibilityManager =
@@ -367,12 +367,9 @@
         get() {
             if (currentSemanticsNodesInvalidated) { // first instance of retrieving all nodes
                 currentSemanticsNodesInvalidated = false
-                field =
-                    trace("generateCurrentSemanticsNodes") {
-                        view.semanticsOwner.getAllUncoveredSemanticsNodesToIntObjectMap()
-                    }
+                field = view.semanticsOwner.getAllUncoveredSemanticsNodesToIntObjectMap()
                 if (isEnabled) {
-                    trace("setTraversalValues") { setTraversalValues() }
+                    setTraversalValues()
                 }
             }
             return field
@@ -497,43 +494,32 @@
     }
 
     private fun createNodeInfo(virtualViewId: Int): AccessibilityNodeInfoCompat? {
-        trace("checkIfDestroyed") {
-            if (
-                view.viewTreeOwners?.lifecycleOwner?.lifecycle?.currentState ==
-                    Lifecycle.State.DESTROYED
-            ) {
-                return null
-            }
+        if (
+            view.viewTreeOwners?.lifecycleOwner?.lifecycle?.currentState ==
+                Lifecycle.State.DESTROYED
+        ) {
+            return null
         }
-        val info: AccessibilityNodeInfoCompat =
-            trace("createAccessibilityNodeInfoObject") { AccessibilityNodeInfoCompat.obtain() }
-        val semanticsNodeWithAdjustedBounds =
-            trace("calculateNodeWithAdjustedBounds") { currentSemanticsNodes[virtualViewId] }
-                ?: return null
+        val info: AccessibilityNodeInfoCompat = AccessibilityNodeInfoCompat.obtain()
+        val semanticsNodeWithAdjustedBounds = currentSemanticsNodes[virtualViewId] ?: return null
         val semanticsNode: SemanticsNode = semanticsNodeWithAdjustedBounds.semanticsNode
-        trace("setParentForAccessibility") {
-            if (virtualViewId == AccessibilityNodeProviderCompat.HOST_VIEW_ID) {
-                info.setParent(view.getParentForAccessibility() as? View)
-            } else {
-                var parentId =
-                    checkPreconditionNotNull(semanticsNode.parent?.id) {
-                        "semanticsNode $virtualViewId has null parent"
-                    }
-                if (parentId == view.semanticsOwner.unmergedRootSemanticsNode.id) {
-                    parentId = AccessibilityNodeProviderCompat.HOST_VIEW_ID
+        if (virtualViewId == AccessibilityNodeProviderCompat.HOST_VIEW_ID) {
+            info.setParent(view.getParentForAccessibility() as? View)
+        } else {
+            var parentId =
+                checkPreconditionNotNull(semanticsNode.parent?.id) {
+                    "semanticsNode $virtualViewId has null parent"
                 }
-                info.setParent(view, parentId)
+            if (parentId == view.semanticsOwner.unmergedRootSemanticsNode.id) {
+                parentId = AccessibilityNodeProviderCompat.HOST_VIEW_ID
             }
+            info.setParent(view, parentId)
         }
         info.setSource(view, virtualViewId)
 
-        trace("setBoundsInScreen") {
-            info.setBoundsInScreen(boundsInScreen(semanticsNodeWithAdjustedBounds))
-        }
+        info.setBoundsInScreen(boundsInScreen(semanticsNodeWithAdjustedBounds))
 
-        trace("populateAccessibilityNodeInfoProperties") {
-            populateAccessibilityNodeInfoProperties(virtualViewId, info, semanticsNode)
-        }
+        populateAccessibilityNodeInfoProperties(virtualViewId, info, semanticsNode)
 
         return info
     }
@@ -1570,14 +1556,13 @@
     @Suppress("DEPRECATION")
     @VisibleForTesting
     private fun createEvent(virtualViewId: Int, eventType: Int): AccessibilityEvent {
-        val event: AccessibilityEvent =
-            trace("obtainAccessibilityEvent") { AccessibilityEvent.obtain(eventType) }
+        val event: AccessibilityEvent = AccessibilityEvent.obtain(eventType)
         event.isEnabled = true
         event.className = ClassName
 
         // Don't allow the client to override these properties.
-        trace("event.packageName") { event.packageName = view.context.packageName }
-        trace("event.setSource") { event.setSource(view, virtualViewId) }
+        event.packageName = view.context.packageName
+        event.setSource(view, virtualViewId)
 
         if (isEnabled) {
             // populate additional information from the node
@@ -2261,15 +2246,11 @@
                 if (isEnabled) {
                     for (i in subtreeChangedLayoutNodes.indices) {
                         val layoutNode = subtreeChangedLayoutNodes.valueAt(i)
-                        trace("sendSubtreeChangeAccessibilityEvents") {
-                            sendSubtreeChangeAccessibilityEvents(
-                                layoutNode,
-                                subtreeChangedSemanticsNodesIds
-                            )
-                        }
-                        trace("sendTypeViewScrolledAccessibilityEvent") {
-                            sendTypeViewScrolledAccessibilityEvent(layoutNode)
-                        }
+                        sendSubtreeChangeAccessibilityEvents(
+                            layoutNode,
+                            subtreeChangedSemanticsNodesIds
+                        )
+                        sendTypeViewScrolledAccessibilityEvent(layoutNode)
                     }
                     subtreeChangedSemanticsNodesIds.clear()
                     // When the bounds of layout nodes change, we will not always get semantics
@@ -2369,22 +2350,19 @@
         }
 
         // When we finally send the event, make sure it is an accessibility-focusable node.
-        val id =
-            trace("GetSemanticsNode") {
-                var semanticsNode =
-                    if (layoutNode.nodes.has(Nodes.Semantics)) layoutNode
-                    else layoutNode.findClosestParentNode { it.nodes.has(Nodes.Semantics) }
+        var semanticsNode =
+            if (layoutNode.nodes.has(Nodes.Semantics)) layoutNode
+            else layoutNode.findClosestParentNode { it.nodes.has(Nodes.Semantics) }
 
-                val config = semanticsNode?.collapsedSemantics ?: return
-                if (!config.isMergingSemanticsOfDescendants) {
-                    semanticsNode
-                        .findClosestParentNode {
-                            it.collapsedSemantics?.isMergingSemanticsOfDescendants == true
-                        }
-                        ?.let { semanticsNode = it }
+        val config = semanticsNode?.collapsedSemantics ?: return
+        if (!config.isMergingSemanticsOfDescendants) {
+            semanticsNode
+                .findClosestParentNode {
+                    it.collapsedSemantics?.isMergingSemanticsOfDescendants == true
                 }
-                semanticsNode?.semanticsId ?: return
-            }
+                ?.let { semanticsNode = it }
+        }
+        val id = semanticsNode?.semanticsId ?: return
 
         if (!subtreeChangedSemanticsNodesIds.add(id)) {
             return
@@ -3175,11 +3153,9 @@
 
     private inner class ComposeAccessibilityNodeProvider : AccessibilityNodeProviderCompat() {
         override fun createAccessibilityNodeInfo(virtualViewId: Int): AccessibilityNodeInfoCompat? {
-            return trace("createAccessibilityNodeInfo") {
-                createNodeInfo(virtualViewId).also {
-                    if (sendingFocusAffectingEvent && virtualViewId == focusedVirtualViewId) {
-                        currentlyFocusedANI = it
-                    }
+            return createNodeInfo(virtualViewId).also {
+                if (sendingFocusAffectingEvent && virtualViewId == focusedVirtualViewId) {
+                    currentlyFocusedANI = it
                 }
             }
         }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt
index 475f5dba..83c30cd 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt
@@ -20,16 +20,13 @@
 import android.graphics.Outline
 import android.os.Build
 import android.view.ContextThemeWrapper
-import android.view.Gravity
 import android.view.KeyEvent
 import android.view.MotionEvent
 import android.view.View
-import android.view.View.OnLayoutChangeListener
 import android.view.ViewGroup
 import android.view.ViewOutlineProvider
 import android.view.Window
 import android.view.WindowManager
-import android.widget.FrameLayout
 import androidx.activity.ComponentDialog
 import androidx.activity.addCallback
 import androidx.compose.runtime.Composable
@@ -60,11 +57,8 @@
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.util.fastMap
 import androidx.compose.ui.util.fastMaxBy
-import androidx.core.view.OnApplyWindowInsetsListener
-import androidx.core.view.ViewCompat
+import androidx.compose.ui.util.fastRoundToInt
 import androidx.core.view.WindowCompat
-import androidx.core.view.WindowInsetsAnimationCompat
-import androidx.core.view.WindowInsetsCompat
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import androidx.lifecycle.findViewTreeViewModelStoreOwner
 import androidx.lifecycle.setViewTreeLifecycleOwner
@@ -83,19 +77,16 @@
  * @property securePolicy Policy for setting [WindowManager.LayoutParams.FLAG_SECURE] on the
  *   dialog's window.
  * @property usePlatformDefaultWidth Whether the width of the dialog's content should be limited to
- *   the platform default, which is smaller than the screen width. It is recommended to use
- *   [decorFitsSystemWindows] set to `false` when [usePlatformDefaultWidth] is false to support
- *   using the entire screen and avoiding UI glitches on some devices when the IME animates in.
+ *   the platform default, which is smaller than the screen width.
  * @property decorFitsSystemWindows Sets [WindowCompat.setDecorFitsSystemWindows] value. Set to
  *   `false` to use WindowInsets. If `false`, the
  *   [soft input mode][WindowManager.LayoutParams.softInputMode] will be changed to
  *   [WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE] and `android:windowIsFloating` is set to
- *   `false` when [decorFitsSystemWindows] is false. When
- *   `targetSdk` >= [Build.VERSION_CODES.VANILLA_ICE_CREAM], [decorFitsSystemWindows] can only be
- *   `false` and this property doesn't have any effect.
+ *   `false` for Android [R][Build.VERSION_CODES.R] and earlier.
  */
 @Immutable
-actual class DialogProperties(
+actual class DialogProperties
+constructor(
     actual val dismissOnBackPress: Boolean = true,
     actual val dismissOnClickOutside: Boolean = true,
     val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
@@ -227,7 +218,6 @@
     private var content: @Composable () -> Unit by mutableStateOf({})
 
     var usePlatformDefaultWidth = false
-    var decorFitsSystemWindows = false
 
     override var shouldCreateCompositionOnAttachedToWindow: Boolean = false
         private set
@@ -239,16 +229,50 @@
         createComposition()
     }
 
+    override fun internalOnMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        if (usePlatformDefaultWidth) {
+            super.internalOnMeasure(widthMeasureSpec, heightMeasureSpec)
+        } else {
+            // usePlatformDefaultWidth false, so don't want to limit the dialog width to the Android
+            // platform default. Therefore, we create a new measure spec for width, which
+            // corresponds to the full screen width. We do the same for height, even if
+            // ViewRootImpl gives it to us from the first measure.
+            val displayWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(displayWidth, MeasureSpec.AT_MOST)
+            val displayHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(displayHeight, MeasureSpec.AT_MOST)
+            super.internalOnMeasure(displayWidthMeasureSpec, displayHeightMeasureSpec)
+        }
+    }
+
+    override fun internalOnLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+        super.internalOnLayout(changed, left, top, right, bottom)
+        // Now set the content size as fixed layout params, such that ViewRootImpl knows
+        // the exact window size.
+        if (!usePlatformDefaultWidth) {
+            val child = getChildAt(0) ?: return
+            window.setLayout(child.measuredWidth, child.measuredHeight)
+        }
+    }
+
+    private val displayWidth: Int
+        get() {
+            val density = context.resources.displayMetrics.density
+            return (context.resources.configuration.screenWidthDp * density).fastRoundToInt()
+        }
+
+    private val displayHeight: Int
+        get() {
+            val density = context.resources.displayMetrics.density
+            return (context.resources.configuration.screenHeightDp * density).fastRoundToInt()
+        }
+
     @Composable
     override fun Content() {
         content()
     }
 }
 
-private fun adjustedDecorFitsSystemWindows(dialogProperties: DialogProperties, context: Context) =
-    dialogProperties.decorFitsSystemWindows &&
-        context.applicationInfo.targetSdkVersion < Build.VERSION_CODES.VANILLA_ICE_CREAM
-
 private class DialogWrapper(
     private var onDismissRequest: () -> Unit,
     private var properties: DialogProperties,
@@ -264,16 +288,16 @@
          */
         ContextThemeWrapper(
             composeView.context,
-            if (adjustedDecorFitsSystemWindows(properties, composeView.context)) {
+            if (
+                Build.VERSION.SDK_INT >= Build.VERSION_CODES.S || properties.decorFitsSystemWindows
+            ) {
                 R.style.DialogWindowTheme
             } else {
                 R.style.FloatingDialogWindowTheme
             }
         )
     ),
-    ViewRootForInspector,
-    OnApplyWindowInsetsListener,
-    OnLayoutChangeListener {
+    ViewRootForInspector {
 
     private val dialogLayout: DialogLayout
 
@@ -284,12 +308,15 @@
     override val subCompositionView: AbstractComposeView
         get() = dialogLayout
 
+    private val defaultSoftInputMode: Int
+
     init {
         val window = window ?: error("Dialog has no window")
+        defaultSoftInputMode =
+            window.attributes.softInputMode and WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST
         window.requestFeature(Window.FEATURE_NO_TITLE)
         window.setBackgroundDrawableResource(android.R.color.transparent)
-        val decorFitsSystemWindows = adjustedDecorFitsSystemWindows(properties, context)
-        WindowCompat.setDecorFitsSystemWindows(window, decorFitsSystemWindows)
+        WindowCompat.setDecorFitsSystemWindows(window, properties.decorFitsSystemWindows)
         dialogLayout =
             DialogLayout(context, window).apply {
                 // Set unique id for AbstractComposeView. This allows state restoration for the
@@ -309,8 +336,10 @@
                         override fun getOutline(view: View, result: Outline) {
                             result.setRect(0, 0, view.width, view.height)
                             // We set alpha to 0 to hide the view's shadow and let the composable to
-                            // draw its own shadow. This still enables us to get the extra space
-                            // needed in the surface.
+                            // draw
+                            // its own shadow. This still enables us to get the extra space needed
+                            // in the
+                            // surface.
                             result.alpha = 0f
                         }
                     }
@@ -330,38 +359,7 @@
 
         // Turn of all clipping so shadows can be drawn outside the window
         (window.decorView as? ViewGroup)?.disableClipping()
-        // Center the ComposeView in a FrameLayout
-        val frameLayout = FrameLayout(context)
-        frameLayout.addView(
-            dialogLayout,
-            FrameLayout.LayoutParams(
-                    FrameLayout.LayoutParams.WRAP_CONTENT,
-                    FrameLayout.LayoutParams.WRAP_CONTENT
-                )
-                .also { it.gravity = Gravity.CENTER }
-        )
-        frameLayout.setOnClickListener { onDismissRequest() }
-        ViewCompat.setOnApplyWindowInsetsListener(frameLayout, this)
-        ViewCompat.setWindowInsetsAnimationCallback(
-            frameLayout,
-            object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
-                override fun onProgress(
-                    insets: WindowInsetsCompat,
-                    runningAnimations: MutableList<WindowInsetsAnimationCompat>
-                ): WindowInsetsCompat {
-                    return insets.inset(
-                        dialogLayout.left,
-                        dialogLayout.top,
-                        frameLayout.width - dialogLayout.right,
-                        frameLayout.height - dialogLayout.bottom
-                    )
-                }
-            }
-        )
-        dialogLayout.addOnLayoutChangeListener(this)
-        frameLayout.addOnLayoutChangeListener(this)
-
-        setContentView(frameLayout)
+        setContentView(dialogLayout)
         dialogLayout.setViewTreeLifecycleOwner(composeView.findViewTreeLifecycleOwner())
         dialogLayout.setViewTreeViewModelStoreOwner(composeView.findViewTreeViewModelStoreOwner())
         dialogLayout.setViewTreeSavedStateRegistryOwner(
@@ -432,42 +430,21 @@
         this.properties = properties
         setSecurePolicy(properties.securePolicy)
         setLayoutDirection(layoutDirection)
+        if (properties.usePlatformDefaultWidth && !dialogLayout.usePlatformDefaultWidth) {
+            // Undo fixed size in internalOnLayout, which would suppress size changes when
+            // usePlatformDefaultWidth is true.
+            window?.setLayout(
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.WRAP_CONTENT
+            )
+        }
         dialogLayout.usePlatformDefaultWidth = properties.usePlatformDefaultWidth
-        val decorFitsSystemWindows = adjustedDecorFitsSystemWindows(properties, context)
-        dialogLayout.decorFitsSystemWindows = decorFitsSystemWindows
-        val window = window
-        if (window != null) {
-            val softInput =
-                when {
-                    decorFitsSystemWindows ->
-                        WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED
-                    Build.VERSION.SDK_INT < Build.VERSION_CODES.S ->
-                        @Suppress("DEPRECATION") WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
-                    else -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
-                }
-            window.setSoftInputMode(softInput)
-            val attrs = window.attributes
-            val measurementWidth =
-                if (properties.usePlatformDefaultWidth) {
-                    WindowManager.LayoutParams.WRAP_CONTENT
-                } else {
-                    WindowManager.LayoutParams.MATCH_PARENT
-                }
-            val measurementHeight =
-                if (properties.usePlatformDefaultWidth || decorFitsSystemWindows) {
-                    WindowManager.LayoutParams.WRAP_CONTENT
-                } else {
-                    WindowManager.LayoutParams.MATCH_PARENT
-                }
-            if (
-                attrs.width != measurementWidth ||
-                    attrs.height != measurementHeight ||
-                    attrs.gravity != Gravity.CENTER
-            ) {
-                attrs.width = measurementWidth
-                attrs.height = measurementHeight
-                attrs.gravity = Gravity.CENTER
-                window.attributes = attrs
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+            if (properties.decorFitsSystemWindows) {
+                window?.setSoftInputMode(defaultSoftInputMode)
+            } else {
+                @Suppress("DEPRECATION")
+                window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
             }
         }
     }
@@ -489,28 +466,6 @@
         // Prevents the dialog from dismissing itself
         return
     }
-
-    override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
-        val left = dialogLayout.left
-        val top = dialogLayout.top
-        val right = v.width - dialogLayout.right
-        val bottom = v.height - dialogLayout.bottom
-        return insets.inset(left, top, right, bottom)
-    }
-
-    override fun onLayoutChange(
-        v: View,
-        left: Int,
-        top: Int,
-        right: Int,
-        bottom: Int,
-        oldLeft: Int,
-        oldTop: Int,
-        oldRight: Int,
-        oldBottom: Int
-    ) {
-        v.requestApplyInsets()
-    }
 }
 
 @Composable
diff --git a/compose/ui/ui/src/androidMain/res/values/styles.xml b/compose/ui/ui/src/androidMain/res/values/styles.xml
index d0e837b..e1211d4 100644
--- a/compose/ui/ui/src/androidMain/res/values/styles.xml
+++ b/compose/ui/ui/src/androidMain/res/values/styles.xml
@@ -19,13 +19,11 @@
     <style name="DialogWindowTheme">
         <item name="android:windowClipToOutline">false</item>
     </style>
-    <!-- Style for decorFitsSystemWindows = false -->
+    <!-- Style for decorFitsSystemWindows = false on API 30 and earlier. WindowInsets won't
+     be set on Dialogs without android:windowIsFloating set to false. -->
     <style name="FloatingDialogWindowTheme">
         <item name="android:windowClipToOutline">false</item>
         <item name="android:dialogTheme">@style/FloatingDialogTheme</item>
-        <item name="android:statusBarColor">@android:color/transparent</item>
-        <item name="android:navigationBarColor">@android:color/transparent</item>
-        <item name="android:backgroundDimEnabled">true</item>
     </style>
     <style name="FloatingDialogTheme">
         <item name="android:windowIsFloating">false</item>
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 2403769..92695e5 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
@@ -60,7 +60,6 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.util.trace
 import androidx.compose.ui.viewinterop.InteropView
 import androidx.compose.ui.viewinterop.InteropViewFactoryHolder
 
@@ -409,27 +408,25 @@
             // whether or not deactivated nodes should be considered removed or not.
             if (!isAttached || isDeactivated) return null
 
-            trace("collapseSemantics") {
-                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
+            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
         }
 
     /**
diff --git a/core/core-telecom/src/main/res/values-af/strings.xml b/core/core-telecom/src/main/res/values-af/strings.xml
new file mode 100644
index 0000000..e5c55e0
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-af/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Oorstuk"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Kabelkopstuk"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Luidspreker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-am/strings.xml b/core/core-telecom/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000..66301fb
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-am/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ማዳመጫ"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ባለ ገመድ ማዳመጫ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ድምፅ ማውጫ"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ar/strings.xml b/core/core-telecom/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000..8963293
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ar/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"سماعة أذن"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"سماعة رأس سلكية"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"مكبِّر صوت"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-as/strings.xml b/core/core-telecom/src/main/res/values-as/strings.xml
new file mode 100644
index 0000000..697b692
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-as/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ইয়েৰপিচ"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"তাঁৰযুক্ত হেডছেট"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"স্পীকাৰ"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-az/strings.xml b/core/core-telecom/src/main/res/values-az/strings.xml
new file mode 100644
index 0000000..e62a4d0
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-az/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Qulaqlıq"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Simli qulaqlıq"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Dinamik"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-b+sr+Latn/strings.xml b/core/core-telecom/src/main/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..6afc996
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Slušalica"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Žičane slušalice"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Zvučnik"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-be/strings.xml b/core/core-telecom/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000..cb6122ec
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-be/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Дынамік"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Правадная гарнітура"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Гучная сувязь"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-bn/strings.xml b/core/core-telecom/src/main/res/values-bn/strings.xml
new file mode 100644
index 0000000..5acdea3
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-bn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ইয়ারপিস"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ওয়্যার্ড হেডসেট"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"স্পিকার"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-bs/strings.xml b/core/core-telecom/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000..6afc996
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-bs/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Slušalica"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Žičane slušalice"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Zvučnik"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ca/strings.xml b/core/core-telecom/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000..4b8b784
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ca/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Auricular"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Auriculars amb cable"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Altaveu"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-cs/strings.xml b/core/core-telecom/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000..9bafe17
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-cs/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Sluchátko"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Kabelová náhlavní souprava"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Reproduktor"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-da/strings.xml b/core/core-telecom/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000..257ec4e
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-da/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Højttaler"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Headset med ledning"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Højttaler"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-de/strings.xml b/core/core-telecom/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000..0ce2c07
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-de/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Kopfhörer"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Kabelgebundenes Headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Lautsprecher"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-el/strings.xml b/core/core-telecom/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000..83770ab
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-el/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Ακουστικό τηλεφώνου"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Ενσύρματα ακουστικά"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Ηχείο"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-en-rAU/strings.xml b/core/core-telecom/src/main/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..ae0ae39
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-en-rAU/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Earpiece"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Wired headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Speaker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-en-rGB/strings.xml b/core/core-telecom/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..ae0ae39
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Earpiece"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Wired headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Speaker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-en-rIN/strings.xml b/core/core-telecom/src/main/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..ae0ae39
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-en-rIN/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Earpiece"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Wired headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Speaker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-es-rUS/strings.xml b/core/core-telecom/src/main/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..1b87fa9
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-es-rUS/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Auricular"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Auriculares con cable"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Bocina"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-es/strings.xml b/core/core-telecom/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000..5af28da
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-es/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Auricular"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Auriculares con cable"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Altavoz"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-et/strings.xml b/core/core-telecom/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000..3d2cc0c
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-et/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Kuular"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Juhtmega peakomplekt"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Kõlar"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-eu/strings.xml b/core/core-telecom/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000..16cc5e9
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-eu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Aurikularra"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Entzungailu kableduna"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Bozgorailua"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-fa/strings.xml b/core/core-telecom/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000..e159d7c
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-fa/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"گوشی"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"هدست سیمی"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"بلندگو"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-fr-rCA/strings.xml b/core/core-telecom/src/main/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..33d0ca4
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-fr-rCA/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Écouteur"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Écouteurs filaires"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Haut-parleur"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-fr/strings.xml b/core/core-telecom/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000..efba6ec
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-fr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Écouteur"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Casque filaire"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Haut-parleur"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-gl/strings.xml b/core/core-telecom/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000..73f3cf5
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-gl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Auricular"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Auriculares con cable"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Altofalante"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-gu/strings.xml b/core/core-telecom/src/main/res/values-gu/strings.xml
new file mode 100644
index 0000000..eb7a9ee
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-gu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ઇયરપીસ"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"વાયર્ડ હૅડસેટ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"સ્પીકર"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-hr/strings.xml b/core/core-telecom/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000..a812b93
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-hr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Zvučnik"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Žičane slušalice"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Zvučnik"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-hu/strings.xml b/core/core-telecom/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000..1175ec2
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-hu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Fülhallgató"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Vezetékes headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Hangszóró"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-hy/strings.xml b/core/core-telecom/src/main/res/values-hy/strings.xml
new file mode 100644
index 0000000..0f1a0d2
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-hy/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Լսափող"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Լարով ականջակալ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Բարձրախոս"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-in/strings.xml b/core/core-telecom/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000..8e053cc
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-in/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Earpiece"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Headset berkabel"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Speaker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-is/strings.xml b/core/core-telecom/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000..c0befd0
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-is/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Hátalari"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Höfuðtól með snúru"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Hátalari"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-iw/strings.xml b/core/core-telecom/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000..9ec7ee9
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-iw/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"אוזניה"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"אוזניות חוטיות"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"רמקול"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-kk/strings.xml b/core/core-telecom/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000..6867ece
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-kk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Телефон динамигі"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Сымды гарнитура"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Динамик"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-km/strings.xml b/core/core-telecom/src/main/res/values-km/strings.xml
new file mode 100644
index 0000000..0fc75bb
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-km/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ឧបករណ៍ស្ដាប់សំឡេង"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"កាស​មាន​ខ្សែ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ឧបករណ៍​បំពង​សំឡេង"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-kn/strings.xml b/core/core-telecom/src/main/res/values-kn/strings.xml
new file mode 100644
index 0000000..4b006c3
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-kn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ಇಯರ್‌ಪೀಸ್‌"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ವೈಯರ್ಡ್ ಹೆಡ್‌ಸೆಟ್‌"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ಸ್ಪೀಕರ್"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ko/strings.xml b/core/core-telecom/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000..6dd6a7d
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ko/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"스피커"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"유선 헤드셋"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"스피커"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ky/strings.xml b/core/core-telecom/src/main/res/values-ky/strings.xml
new file mode 100644
index 0000000..4de5b55
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ky/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Кулакчын"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Зымдуу гарнитура"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Динамик"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-lt/strings.xml b/core/core-telecom/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000..ab5b490
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-lt/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Garsiakalbis prie ausies"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Laidinės ausinės"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Garsiakalbis"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-lv/strings.xml b/core/core-telecom/src/main/res/values-lv/strings.xml
new file mode 100644
index 0000000..dbbe825
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-lv/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Auss skaļrunis"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Vadu austiņas"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Skaļrunis"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-mk/strings.xml b/core/core-telecom/src/main/res/values-mk/strings.xml
new file mode 100644
index 0000000..73a43de
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-mk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Слушалка"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Жичени слушалки"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Звучник"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-mn/strings.xml b/core/core-telecom/src/main/res/values-mn/strings.xml
new file mode 100644
index 0000000..3f929e9
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-mn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Чихний спикер"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Утастай чихэвч"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Чанга яригч"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-mr/strings.xml b/core/core-telecom/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000..343c6c2
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-mr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"इअरपीस"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"वायर्ड हेडसेट"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"स्पीकर"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ms/strings.xml b/core/core-telecom/src/main/res/values-ms/strings.xml
new file mode 100644
index 0000000..1ffead0
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ms/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Alat dengar"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Set kepala berwayar"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Pembesar suara"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-my/strings.xml b/core/core-telecom/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000..a62aea0
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-my/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"တယ်လီဖုန်းနားခွက်"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ကြိုးတပ် မိုက်ခွက်ပါနားကြပ်"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"စပီကာ"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-nb/strings.xml b/core/core-telecom/src/main/res/values-nb/strings.xml
new file mode 100644
index 0000000..387722e
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-nb/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Ørehøyttaler"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Hodetelefoner med ledning"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Høyttaler"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-nl/strings.xml b/core/core-telecom/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000..c496439
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-nl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Oortelefoon"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Bedrade headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Speaker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-or/strings.xml b/core/core-telecom/src/main/res/values-or/strings.xml
new file mode 100644
index 0000000..2a480c7
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-or/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ଇୟରପିସ"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ତାରଯୁକ୍ତ ହେଡସେଟ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ସ୍ପିକର"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-pa/strings.xml b/core/core-telecom/src/main/res/values-pa/strings.xml
new file mode 100644
index 0000000..ebc4300
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-pa/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ਈਅਰਪੀਸ"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ਤਾਰ ਵਾਲਾ ਹੈੱਡਸੈੱਟ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ਸਪੀਕਰ"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-pl/strings.xml b/core/core-telecom/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000..768b794
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-pl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Słuchawka"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Przewodowy zestaw słuchawkowy"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Głośnik"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-pt-rBR/strings.xml b/core/core-telecom/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..de52295
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Minifone de ouvido"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Fone de ouvido com fio"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Alto-falante"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-pt/strings.xml b/core/core-telecom/src/main/res/values-pt/strings.xml
new file mode 100644
index 0000000..de52295
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-pt/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Minifone de ouvido"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Fone de ouvido com fio"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Alto-falante"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ro/strings.xml b/core/core-telecom/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000..a1b63da
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ro/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Cască"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Set de căști-microfon cu fir"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Difuzor"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ru/strings.xml b/core/core-telecom/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000..9f1c287
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ru/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Наушник"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Проводная гарнитура"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Колонка"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-si/strings.xml b/core/core-telecom/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000..748d5c2
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-si/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"සවන් කඩ"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"රැහැන්ගත කළ හෙඩ්සෙට්"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ස්පීකරය"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-sk/strings.xml b/core/core-telecom/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000..b6075f4
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-sk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Slúchadlo"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Káblové slúchadlá s mikrofónom"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Reproduktor"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-sl/strings.xml b/core/core-telecom/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000..5ca1886
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-sl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Slušalka"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Žične slušalke z mikrofonom"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Zvočnik"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-sq/strings.xml b/core/core-telecom/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000..c932e8d
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-sq/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Receptor"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Kufje me tel"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Altoparlant"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-sr/strings.xml b/core/core-telecom/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000..199a682
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-sr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Слушалица"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Жичане слушалице"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Звучник"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-sv/strings.xml b/core/core-telecom/src/main/res/values-sv/strings.xml
new file mode 100644
index 0000000..aec1523
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-sv/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Lur"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Kabelanslutet headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Högtalare"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-sw/strings.xml b/core/core-telecom/src/main/res/values-sw/strings.xml
new file mode 100644
index 0000000..af27136d
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-sw/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Spika ya sikioni"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Vifaa vya sauti vyenye waya"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Spika"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ta/strings.xml b/core/core-telecom/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000..b3678bb
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ta/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ஒலி கேட்கும் பகுதி"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"வயர் ஹெட்செட்"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ஸ்பீக்கர்"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-te/strings.xml b/core/core-telecom/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000..e387597
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-te/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ఇయర్‌పీస్"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"వైర్ ఉన్న హెడ్‌సెట్"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"స్పీకర్"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-th/strings.xml b/core/core-telecom/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000..103ceb1
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-th/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"หูฟังโทรศัพท์"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"ชุดหูฟังแบบมีสาย"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"ลำโพง"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-tl/strings.xml b/core/core-telecom/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000..50ac56c
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-tl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Earpiece"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Wired na headset"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Speaker"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-tr/strings.xml b/core/core-telecom/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000..600c6d2
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-tr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Kulaklık"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Kablolu mikrofonlu kulaklık"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Hoparlör"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-uk/strings.xml b/core/core-telecom/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000..d8580f9
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-uk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Динамік"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Дротова гарнітура"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Колонка"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-ur/strings.xml b/core/core-telecom/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000..d577f0b
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-ur/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"ایئر پیس"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"تار والا ہیڈ سیٹ"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"اسپیکر"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-uz/strings.xml b/core/core-telecom/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000..679f5dd
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-uz/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Quloq karnaychasi"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Simli garnitura"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Karnay"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-vi/strings.xml b/core/core-telecom/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000..a4c82f9
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-vi/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Loa tai nghe"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Tai nghe có dây"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Loa ngoài"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-zh-rCN/strings.xml b/core/core-telecom/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..0d4efb7
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"手机听筒"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"有线头戴式耳机"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"扬声器"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-zh-rHK/strings.xml b/core/core-telecom/src/main/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..4e99591
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-zh-rHK/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"聽筒"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"有線耳機"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"喇叭"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-zh-rTW/strings.xml b/core/core-telecom/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..4c586c7
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"耳機"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"有線耳機"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"喇叭"</string>
+</resources>
diff --git a/core/core-telecom/src/main/res/values-zu/strings.xml b/core/core-telecom/src/main/res/values-zu/strings.xml
new file mode 100644
index 0000000..7aab3c5
--- /dev/null
+++ b/core/core-telecom/src/main/res/values-zu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="callendpoint_name_earpiece" msgid="4519059065203201851">"Isipikha sendlebe"</string>
+    <string name="callendpoint_name_wiredheadset" msgid="6723516311603411573">"Iheadset enentambo"</string>
+    <string name="callendpoint_name_speaker" msgid="623806810712383295">"Isipikha"</string>
+</resources>
diff --git a/credentials/credentials-play-services-auth/build.gradle b/credentials/credentials-play-services-auth/build.gradle
index 30d02c4..63d01b8 100644
--- a/credentials/credentials-play-services-auth/build.gradle
+++ b/credentials/credentials-play-services-auth/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -87,4 +89,5 @@
     inceptionYear = "2022"
     description = "sign into apps using play-services-auth library"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/credentials/credentials/build.gradle b/credentials/credentials/build.gradle
index eb89d1a..ce89b90 100644
--- a/credentials/credentials/build.gradle
+++ b/credentials/credentials/build.gradle
@@ -31,7 +31,7 @@
 
 dependencies {
     api("androidx.annotation:annotation:1.8.1")
-    api(project(":biometric:biometric-ktx"))
+    api("androidx.biometric:biometric-ktx:1.4.0-alpha02")
     api(libs.kotlinStdlib)
     implementation(libs.kotlinCoroutinesCore)
     implementation("androidx.core:core:1.15.0-alpha01")
diff --git a/datastore/datastore-core/build.gradle b/datastore/datastore-core/build.gradle
index f184764..d509e6a 100644
--- a/datastore/datastore-core/build.gradle
+++ b/datastore/datastore-core/build.gradle
@@ -28,8 +28,6 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("com.google.protobuf")
-    id ("kotlin-parcelize")
 }
 
 android {
@@ -42,26 +40,6 @@
     namespace "androidx.datastore.core"
 }
 
-protobuf {
-    protoc {
-        artifact = libs.protobufCompiler.get()
-    }
-    generateProtoTasks {
-        all().each { task ->
-            task.builtins {
-                java {
-                    option "lite"
-                }
-            }
-        }
-    }
-}
-
-def protoDir = project.layout.projectDirectory.dir("src/androidInstrumentedTest/proto")
-tasks.named("extractAndroidTestProto").configure {
-    it.inputFiles.from(project.files(protoDir))
-}
-
 androidXMultiplatform {
     jvm()
     mac()
@@ -137,7 +115,6 @@
         androidInstrumentedTest {
             dependsOn(commonJvmTest)
             dependencies {
-                implementation(libs.protobufLite)
                 implementation(libs.truth)
                 implementation(project(":internal-testutils-truth"))
                 implementation(libs.testRunner)
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/AndroidManifest.xml b/datastore/datastore-core/src/androidInstrumentedTest/AndroidManifest.xml
index c25da00..4ec52f2f 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/AndroidManifest.xml
+++ b/datastore/datastore-core/src/androidInstrumentedTest/AndroidManifest.xml
@@ -15,16 +15,5 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
-    <application>
-        <service android:name="androidx.datastore.core.twoWayIpc.TwoWayIpcService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":TwoWayIpcService" />
-        <service android:name="androidx.datastore.core.twoWayIpc.TwoWayIpcService2"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":TwoWayIpcService2" />
-    </application>
-
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 </manifest>
diff --git a/datastore/datastore-preferences-core/build.gradle b/datastore/datastore-preferences-core/build.gradle
index efa4b1f..9dfab0a 100644
--- a/datastore/datastore-preferences-core/build.gradle
+++ b/datastore/datastore-preferences-core/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
@@ -118,4 +120,5 @@
     description = "Android Preferences DataStore without the Android Dependencies"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = false
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/datastore/datastore-preferences-rxjava2/build.gradle b/datastore/datastore-preferences-rxjava2/build.gradle
index aef9070..30c019c 100644
--- a/datastore/datastore-preferences-rxjava2/build.gradle
+++ b/datastore/datastore-preferences-rxjava2/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -68,4 +70,5 @@
     inceptionYear = "2020"
     description = "Android DataStore Core - contains wrappers for using DataStore using RxJava2"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/datastore/datastore-preferences-rxjava3/build.gradle b/datastore/datastore-preferences-rxjava3/build.gradle
index d168af4..b9208ea 100644
--- a/datastore/datastore-preferences-rxjava3/build.gradle
+++ b/datastore/datastore-preferences-rxjava3/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -68,4 +70,5 @@
     inceptionYear = "2020"
     description = "Android DataStore Core - contains wrappers for using DataStore using RxJava2"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/datastore/datastore-preferences/build.gradle b/datastore/datastore-preferences/build.gradle
index 1bf3287..9fb7310 100644
--- a/datastore/datastore-preferences/build.gradle
+++ b/datastore/datastore-preferences/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
 
@@ -98,4 +100,5 @@
     inceptionYear = "2020"
     description = "Android Preferences DataStore"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/datastore/integration-tests/testapp/build.gradle b/datastore/integration-tests/testapp/build.gradle
new file mode 100644
index 0000000..8266634
--- /dev/null
+++ b/datastore/integration-tests/testapp/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+    id("com.google.protobuf")
+    id ("kotlin-parcelize")
+}
+
+android {
+    namespace "androidx.datastore.testapp"
+}
+
+protobuf {
+    protoc {
+        artifact = libs.protobufCompiler.get()
+    }
+    generateProtoTasks {
+        all().each { task ->
+            task.builtins {
+                java {
+                    option "lite"
+                }
+            }
+        }
+    }
+}
+
+dependencies {
+    implementation(libs.okio)
+    implementation(libs.protobufLite)
+    implementation("androidx.lifecycle:lifecycle-service:2.6.1")
+    implementation(project(":datastore:datastore-core"))
+    implementation(project(":datastore:datastore-core-okio"))
+
+    androidTestImplementation(libs.kotlinCoroutinesTest)
+    androidTestImplementation(libs.kotlinTest)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(project(":internal-testutils-truth"))
+    androidTestImplementation(project(":internal-testutils-datastore"))
+    androidTestImplementation(project(":kruth:kruth"))
+}
diff --git a/datastore/integration-tests/testapp/src/androidTest/AndroidManifest.xml b/datastore/integration-tests/testapp/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..867fda8
--- /dev/null
+++ b/datastore/integration-tests/testapp/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+    <application>
+        <service android:name="androidx.datastore.testapp.twoWayIpc.TwoWayIpcService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":TwoWayIpcService" />
+        <service android:name="androidx.datastore.testapp.twoWayIpc.TwoWayIpcService2"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":TwoWayIpcService2" />
+    </application>
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+</manifest>
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/InterProcessCompletableTest.kt b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/InterProcessCompletableTest.kt
similarity index 89%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/InterProcessCompletableTest.kt
rename to datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/InterProcessCompletableTest.kt
index 9623f58..c6233a5 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/InterProcessCompletableTest.kt
+++ b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/InterProcessCompletableTest.kt
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess
+package androidx.datastore.testapp.multiprocess
 
 import android.os.Parcelable
-import androidx.datastore.core.twoWayIpc.InterProcessCompletable
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.IpcUnit
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testapp.twoWayIpc.InterProcessCompletable
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.IpcUnit
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.async
 import kotlinx.coroutines.yield
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultiProcessDataStoreIpcTest.kt b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultiProcessDataStoreIpcTest.kt
similarity index 96%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultiProcessDataStoreIpcTest.kt
rename to datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultiProcessDataStoreIpcTest.kt
index 86887fc..b13ee2d 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultiProcessDataStoreIpcTest.kt
+++ b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultiProcessDataStoreIpcTest.kt
@@ -14,21 +14,24 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess
+// Parcelize object is testing internal implementation of datastore-core library
+@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "CANNOT_OVERRIDE_INVISIBLE_MEMBER")
+
+package androidx.datastore.testapp.multiprocess
 
 import androidx.datastore.core.CorruptionException
 import androidx.datastore.core.CorruptionHandler
 import androidx.datastore.core.IOException
 import androidx.datastore.core.SharedCounter
-import androidx.datastore.core.multiprocess.ipcActions.ReadTextAction
-import androidx.datastore.core.multiprocess.ipcActions.SetTextAction
-import androidx.datastore.core.multiprocess.ipcActions.StorageVariant
-import androidx.datastore.core.multiprocess.ipcActions.createMultiProcessTestDatastore
-import androidx.datastore.core.multiprocess.ipcActions.datastore
-import androidx.datastore.core.twoWayIpc.InterProcessCompletable
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.IpcUnit
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testapp.multiprocess.ipcActions.ReadTextAction
+import androidx.datastore.testapp.multiprocess.ipcActions.SetTextAction
+import androidx.datastore.testapp.multiprocess.ipcActions.StorageVariant
+import androidx.datastore.testapp.multiprocess.ipcActions.createMultiProcessTestDatastore
+import androidx.datastore.testapp.multiprocess.ipcActions.datastore
+import androidx.datastore.testapp.twoWayIpc.InterProcessCompletable
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.IpcUnit
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import androidx.datastore.testing.TestMessageProto.FooProto
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CompletableDeferred
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultiProcessTestRule.kt b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultiProcessTestRule.kt
similarity index 92%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultiProcessTestRule.kt
rename to datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultiProcessTestRule.kt
index c2cbb5b..82df64d 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultiProcessTestRule.kt
+++ b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultiProcessTestRule.kt
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess
+package androidx.datastore.testapp.multiprocess
 
-import androidx.datastore.core.twoWayIpc.TwoWayIpcConnection
-import androidx.datastore.core.twoWayIpc.TwoWayIpcService
-import androidx.datastore.core.twoWayIpc.TwoWayIpcService2
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcConnection
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcService
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcService2
 import androidx.test.platform.app.InstrumentationRegistry
 import java.util.concurrent.atomic.AtomicBoolean
 import kotlin.time.Duration.Companion.seconds
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultipleDataStoresInMultipleProcessesTest.kt b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultipleDataStoresInMultipleProcessesTest.kt
similarity index 91%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultipleDataStoresInMultipleProcessesTest.kt
rename to datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultipleDataStoresInMultipleProcessesTest.kt
index 00442d7..9b07814 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/MultipleDataStoresInMultipleProcessesTest.kt
+++ b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/MultipleDataStoresInMultipleProcessesTest.kt
@@ -14,19 +14,22 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess
+// Parcelize object is testing internal implementation of datastore-core library
+@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
 
-import androidx.datastore.core.multiprocess.ipcActions.ReadTextAction
-import androidx.datastore.core.multiprocess.ipcActions.SetTextAction
-import androidx.datastore.core.multiprocess.ipcActions.StorageVariant
-import androidx.datastore.core.multiprocess.ipcActions.createMultiProcessTestDatastore
-import androidx.datastore.core.multiprocess.ipcActions.datastore
-import androidx.datastore.core.twoWayIpc.CompositeServiceSubjectModel
-import androidx.datastore.core.twoWayIpc.InterProcessCompletable
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.IpcUnit
-import androidx.datastore.core.twoWayIpc.SubjectReadWriteProperty
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+package androidx.datastore.testapp.multiprocess
+
+import androidx.datastore.testapp.multiprocess.ipcActions.ReadTextAction
+import androidx.datastore.testapp.multiprocess.ipcActions.SetTextAction
+import androidx.datastore.testapp.multiprocess.ipcActions.StorageVariant
+import androidx.datastore.testapp.multiprocess.ipcActions.createMultiProcessTestDatastore
+import androidx.datastore.testapp.multiprocess.ipcActions.datastore
+import androidx.datastore.testapp.twoWayIpc.CompositeServiceSubjectModel
+import androidx.datastore.testapp.twoWayIpc.InterProcessCompletable
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.IpcUnit
+import androidx.datastore.testapp.twoWayIpc.SubjectReadWriteProperty
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import androidx.datastore.testing.TestMessageProto.FooProto
 import androidx.kruth.assertThat
 import kotlin.time.Duration.Companion.seconds
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/TwoWayIpcTest.kt b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/TwoWayIpcTest.kt
similarity index 95%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/TwoWayIpcTest.kt
rename to datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/TwoWayIpcTest.kt
index 3cf76e5..a6d77b6 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/TwoWayIpcTest.kt
+++ b/datastore/integration-tests/testapp/src/androidTest/java/androidx/datastore/testapp/multiprocess/TwoWayIpcTest.kt
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess
+package androidx.datastore.testapp.multiprocess
 
 import android.os.Parcelable
-import androidx.datastore.core.twoWayIpc.CompositeServiceSubjectModel
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testapp.twoWayIpc.CompositeServiceSubjectModel
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import com.google.common.truth.Truth.assertThat
 import kotlinx.parcelize.Parcelize
 import org.junit.Rule
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/ProtoOkioSerializer.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/ProtoOkioSerializer.kt
similarity index 95%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/ProtoOkioSerializer.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/ProtoOkioSerializer.kt
index cb319f1..6a291b8 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/ProtoOkioSerializer.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/ProtoOkioSerializer.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core
+package androidx.datastore.testapp
 
+import androidx.datastore.core.CorruptionException
 import androidx.datastore.core.okio.OkioSerializer
 import com.google.protobuf.ExtensionRegistryLite
 import com.google.protobuf.InvalidProtocolBufferException
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/ProtoSerializer.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/ProtoSerializer.kt
similarity index 92%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/ProtoSerializer.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/ProtoSerializer.kt
index 587f24f..f9eb2e3 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/ProtoSerializer.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/ProtoSerializer.kt
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core
+package androidx.datastore.testapp
 
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.Serializer
 import com.google.protobuf.ExtensionRegistryLite
 import com.google.protobuf.InvalidProtocolBufferException
 import com.google.protobuf.MessageLite
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/CreateDatastoreAction.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/CreateDatastoreAction.kt
similarity index 87%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/CreateDatastoreAction.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/CreateDatastoreAction.kt
index 4890be9..cb3ef18 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/CreateDatastoreAction.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/CreateDatastoreAction.kt
@@ -14,24 +14,28 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess.ipcActions
+// Parcelize object is testing internal implementation of datastore-core library
+@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
 
+package androidx.datastore.testapp.multiprocess.ipcActions
+
+import android.annotation.SuppressLint
 import android.os.Parcelable
 import androidx.datastore.core.CorruptionHandler
 import androidx.datastore.core.DataStore
 import androidx.datastore.core.DataStoreImpl
 import androidx.datastore.core.FileStorage
 import androidx.datastore.core.MultiProcessCoordinator
-import androidx.datastore.core.ProtoOkioSerializer
-import androidx.datastore.core.ProtoSerializer
 import androidx.datastore.core.Serializer
 import androidx.datastore.core.handlers.NoOpCorruptionHandler
 import androidx.datastore.core.okio.OkioSerializer
 import androidx.datastore.core.okio.OkioStorage
-import androidx.datastore.core.twoWayIpc.CompositeServiceSubjectModel
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.SubjectReadWriteProperty
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testapp.ProtoOkioSerializer
+import androidx.datastore.testapp.ProtoSerializer
+import androidx.datastore.testapp.twoWayIpc.CompositeServiceSubjectModel
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.SubjectReadWriteProperty
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import androidx.datastore.testing.TestMessageProto.FooProto
 import com.google.protobuf.ExtensionRegistryLite
 import java.io.File
@@ -117,6 +121,7 @@
     )
 }
 
+@SuppressLint("BanParcelableUsage")
 @Parcelize
 private class CreateDatastoreAction(
     private val filePath: String,
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/ReadTextAction.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/ReadTextAction.kt
similarity index 67%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/ReadTextAction.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/ReadTextAction.kt
index eafa6b5..0162238 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/ReadTextAction.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/ReadTextAction.kt
@@ -14,17 +14,23 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess.ipcActions
+// Parcelize object is testing internal implementation of datastore-core library
+@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
 
+package androidx.datastore.testapp.multiprocess.ipcActions
+
+import android.annotation.SuppressLint
 import android.os.Parcelable
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import kotlinx.coroutines.flow.first
 import kotlinx.parcelize.Parcelize
 
 @Parcelize
 internal class ReadTextAction : IpcAction<ReadTextAction.TextValue>() {
-    @Parcelize data class TextValue(val value: String) : Parcelable
+    @SuppressLint("BanParcelableUsage")
+    @Parcelize
+    data class TextValue(val value: String) : Parcelable
 
     override suspend fun invokeInRemoteProcess(subject: TwoWayIpcSubject): TextValue {
         return TextValue(subject.datastore.data.first().text)
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/SetTextAction.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/SetTextAction.kt
similarity index 73%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/SetTextAction.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/SetTextAction.kt
index ce98deb..929b23f 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/multiprocess/ipcActions/SetTextAction.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/multiprocess/ipcActions/SetTextAction.kt
@@ -14,15 +14,20 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.multiprocess.ipcActions
+// Parcelize object is testing internal implementation of datastore-core library
+@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
 
+package androidx.datastore.testapp.multiprocess.ipcActions
+
+import android.annotation.SuppressLint
 import android.os.Parcelable
-import androidx.datastore.core.twoWayIpc.InterProcessCompletable
-import androidx.datastore.core.twoWayIpc.IpcAction
-import androidx.datastore.core.twoWayIpc.IpcUnit
-import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testapp.twoWayIpc.InterProcessCompletable
+import androidx.datastore.testapp.twoWayIpc.IpcAction
+import androidx.datastore.testapp.twoWayIpc.IpcUnit
+import androidx.datastore.testapp.twoWayIpc.TwoWayIpcSubject
 import kotlinx.parcelize.Parcelize
 
+@SuppressLint("BanParcelableUsage")
 @Parcelize
 internal class SetTextAction(
     private val value: String,
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/CompositeServiceSubjectModel.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/CompositeServiceSubjectModel.kt
similarity index 94%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/CompositeServiceSubjectModel.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/CompositeServiceSubjectModel.kt
index 3b8dd64..741bb88 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/CompositeServiceSubjectModel.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/CompositeServiceSubjectModel.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
+//noinspection BanConcurrentHashMap
 import java.util.concurrent.ConcurrentHashMap
 
 /**
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/InterProcessCompletable.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/InterProcessCompletable.kt
similarity index 96%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/InterProcessCompletable.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/InterProcessCompletable.kt
index 46eaffa..4e5d506 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/InterProcessCompletable.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/InterProcessCompletable.kt
@@ -14,14 +14,16 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
+import android.annotation.SuppressLint
 import android.os.Parcelable
 import java.util.UUID
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.parcelize.Parcelize
 
 /** A [Parcelable] [CompletableDeferred] implementation that can be shared across processes. */
+@SuppressLint("BanParcelableUsage")
 @Parcelize
 internal class InterProcessCompletable<T : Parcelable>(
     private val key: String = UUID.randomUUID().toString(),
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/IpcAction.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/IpcAction.kt
similarity index 85%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/IpcAction.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/IpcAction.kt
index fa2de84..086510f 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/IpcAction.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/IpcAction.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
+import android.annotation.SuppressLint
 import android.os.Parcelable
 import kotlinx.parcelize.Parcelize
 
@@ -25,4 +26,4 @@
 }
 
 /** Utility object for [IpcAction]s that do not return a value. */
-@Parcelize object IpcUnit : Parcelable
+@SuppressLint("BanParcelableUsage") @Parcelize object IpcUnit : Parcelable
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/IpcLogger.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/IpcLogger.kt
similarity index 96%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/IpcLogger.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/IpcLogger.kt
index 628ff8b..278f16d 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/IpcLogger.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/IpcLogger.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
 import android.app.Application
 import android.os.Build
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcBus.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcBus.kt
similarity index 97%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcBus.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcBus.kt
index 4768068..3e84a15 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcBus.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcBus.kt
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
 import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
 import android.os.Message
 import android.os.Messenger
-import androidx.datastore.core.twoWayIpc.IpcLogger.log
+import androidx.datastore.testapp.twoWayIpc.IpcLogger.log
 import java.util.UUID
 import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.CompletableDeferred
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcConnection.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcConnection.kt
similarity index 98%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcConnection.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcConnection.kt
index e153d5d..d37575e 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcConnection.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcConnection.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
 import android.content.ComponentName
 import android.content.Context
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcService.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcService.kt
similarity index 95%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcService.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcService.kt
index 9834950..2fb7ec2 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcService.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcService.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
 import android.content.Intent
 import android.os.Handler
@@ -44,7 +44,7 @@
  * It properly scopes those subjects and destroys their scopes when the Service is destroyed,
  * allowing tests to properly maintain resources.
  *
- * @see androidx.datastore.core.multiprocess.MultiProcessTestRule
+ * @see androidx.datastore.testapp.multiprocess.MultiProcessTestRule
  */
 open class TwoWayIpcService : LifecycleService() {
     private val subjects = mutableListOf<TwoWayIpcSubject>()
@@ -89,6 +89,7 @@
         )
 
     override fun onBind(intent: Intent): IBinder? {
+        super.onBind(intent)
         return messenger.binder
     }
 
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcSubject.kt b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcSubject.kt
similarity index 98%
rename from datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcSubject.kt
rename to datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcSubject.kt
index 8c6cd3f..c6689a3 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/twoWayIpc/TwoWayIpcSubject.kt
+++ b/datastore/integration-tests/testapp/src/main/java/androidx/datastore/testapp/twoWayIpc/TwoWayIpcSubject.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.datastore.core.twoWayIpc
+package androidx.datastore.testapp.twoWayIpc
 
 import android.os.Bundle
 import android.os.Parcelable
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/proto/test.proto b/datastore/integration-tests/testapp/src/main/proto/test.proto
similarity index 100%
rename from datastore/datastore-core/src/androidInstrumentedTest/proto/test.proto
rename to datastore/integration-tests/testapp/src/main/proto/test.proto
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index f0650b2..d1966329 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -223,31 +223,31 @@
     docs("androidx.media2:media2-widget:1.3.0")
     docs("androidx.media:media:1.7.0")
     // androidx.media3 is not hosted in androidx
-    docsWithoutApiSince("androidx.media3:media3-cast:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-common:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-container:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-database:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-datasource:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-datasource-cronet:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-datasource-okhttp:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-datasource-rtmp:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-decoder:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-effect:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-dash:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-hls:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-ima:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-rtsp:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-smoothstreaming:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-workmanager:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-extractor:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-muxer:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-session:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-test-utils:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-test-utils-robolectric:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-transformer:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-ui:1.4.0")
-    docsWithoutApiSince("androidx.media3:media3-ui-leanback:1.4.0")
+    docsWithoutApiSince("androidx.media3:media3-cast:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-common:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-container:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-database:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-datasource:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-datasource-cronet:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-datasource-okhttp:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-datasource-rtmp:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-decoder:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-effect:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-dash:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-hls:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-ima:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-rtsp:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-smoothstreaming:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-workmanager:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-extractor:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-muxer:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-session:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-test-utils:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-test-utils-robolectric:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-transformer:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-ui:1.4.1")
+    docsWithoutApiSince("androidx.media3:media3-ui-leanback:1.4.1")
     docs("androidx.mediarouter:mediarouter:1.7.0")
     docs("androidx.mediarouter:mediarouter-testing:1.7.0")
     docs("androidx.metrics:metrics-performance:1.0.0-beta01")
diff --git a/emoji2/emoji2-emojipicker/src/main/res/values-ar/strings.xml b/emoji2/emoji2-emojipicker/src/main/res/values-ar/strings.xml
index 4d42ff9..a35d75c 100644
--- a/emoji2/emoji2-emojipicker/src/main/res/values-ar/strings.xml
+++ b/emoji2/emoji2-emojipicker/src/main/res/values-ar/strings.xml
@@ -18,7 +18,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="emoji_category_recent" msgid="7142376595414250279">"المستخدمة حديثًا"</string>
-    <string name="emoji_category_emotions" msgid="1570830970240985537">"الوجوه المبتسمة والرموز التعبيرية"</string>
+    <string name="emoji_category_emotions" msgid="1570830970240985537">"الوجوه المبتسمة ورموز الإيموجي"</string>
     <string name="emoji_category_people" msgid="7968173366822927025">"الأشخاص"</string>
     <string name="emoji_category_animals_nature" msgid="4640771324837307541">"الحيوانات والطبيعة"</string>
     <string name="emoji_category_food_drink" msgid="1189971856721244395">"المأكولات والمشروبات"</string>
@@ -27,11 +27,11 @@
     <string name="emoji_category_objects" msgid="6106115586332708067">"عناصر متنوعة"</string>
     <string name="emoji_category_symbols" msgid="5626171724310261787">"الرموز"</string>
     <string name="emoji_category_flags" msgid="6185639503532784871">"الأعلام"</string>
-    <string name="emoji_empty_non_recent_category" msgid="288822832574892625">"لا تتوفر أي رموز تعبيرية."</string>
-    <string name="emoji_empty_recent_category" msgid="7863877827879290200">"لم تستخدم أي رموز تعبيرية حتى الآن."</string>
-    <string name="emoji_bidirectional_switcher_content_desc" msgid="5084600168354220605">"مفتاح ثنائي الاتجاه للرموز التعبيرية"</string>
+    <string name="emoji_empty_non_recent_category" msgid="288822832574892625">"لا تتوفر أي رموز إيموجي."</string>
+    <string name="emoji_empty_recent_category" msgid="7863877827879290200">"لم تستخدم أي رموز إيموجي حتى الآن."</string>
+    <string name="emoji_bidirectional_switcher_content_desc" msgid="5084600168354220605">"مفتاح ثنائي الاتجاه لرموز الإيموجي"</string>
     <string name="emoji_bidirectional_switcher_clicked_desc" msgid="5055290162204827523">"تم تغيير اتجاه الإيموجي"</string>
-    <string name="emoji_variant_selector_content_desc" msgid="2898934883418401376">"أداة اختيار الرموز التعبيرية"</string>
+    <string name="emoji_variant_selector_content_desc" msgid="2898934883418401376">"أداة اختيار رموز الإيموجي"</string>
     <string name="emoji_variant_content_desc_template" msgid="6381933050671041489">"‏%1$s و%2$s"</string>
     <string name="emoji_skin_tone_shadow_content_desc" msgid="1759906883307507376">"الظل"</string>
     <string name="emoji_skin_tone_light_content_desc" msgid="1052239040923092881">"بشرة فاتحة"</string>
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LowLatencyCanvasViewTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LowLatencyCanvasViewTest.kt
index dd8de283..299c232 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LowLatencyCanvasViewTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LowLatencyCanvasViewTest.kt
@@ -115,7 +115,7 @@
                 val resumeLatch = CountDownLatch(1)
                 val drawLatch = CountDownLatch(1)
                 var lowLatencyView: LowLatencyCanvasView? = null
-                scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
+                scenario.onActivity {
                     val view = it.getLowLatencyCanvasView()
                     view.post { drawLatch.countDown() }
                     resumeLatch.countDown()
@@ -207,9 +207,7 @@
                     }
                 },
             scenarioCallback = { scenario ->
-                scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
-                    it.getLowLatencyCanvasView().renderFrontBufferedLayer()
-                }
+                scenario.onActivity { it.getLowLatencyCanvasView().renderFrontBufferedLayer() }
                 assertTrue(renderFrontBufferLatch.await(3000, TimeUnit.MILLISECONDS))
             },
             validateBitmap = { bitmap, left, top, right, bottom ->
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlUtils.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlUtils.kt
index 966c457..b417a45 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlUtils.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlUtils.kt
@@ -49,36 +49,32 @@
             var surfaceView: SurfaceView? = null
             val destroyLatch = CountDownLatch(1)
             val scenario =
-                ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                    .moveToState(Lifecycle.State.CREATED)
-                    .onActivity {
-                        it.setDestroyCallback { destroyLatch.countDown() }
-                        val callback =
-                            object : SurfaceHolder.Callback {
-                                override fun surfaceCreated(sh: SurfaceHolder) {
-                                    surfaceView = it.mSurfaceView
-                                    onSurfaceCreated(surfaceView!!, setupLatch)
-                                }
-
-                                override fun surfaceChanged(
-                                    holder: SurfaceHolder,
-                                    format: Int,
-                                    width: Int,
-                                    height: Int
-                                ) {
-                                    // NO-OP
-                                }
-
-                                override fun surfaceDestroyed(holder: SurfaceHolder) {
-                                    // NO-OP
-                                }
+                ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java).onActivity {
+                    it.setDestroyCallback { destroyLatch.countDown() }
+                    val callback =
+                        object : SurfaceHolder.Callback {
+                            override fun surfaceCreated(sh: SurfaceHolder) {
+                                surfaceView = it.mSurfaceView
+                                onSurfaceCreated(surfaceView!!, setupLatch)
                             }
 
-                        it.addSurface(it.mSurfaceView, callback)
-                        surfaceView = it.mSurfaceView
-                    }
+                            override fun surfaceChanged(
+                                holder: SurfaceHolder,
+                                format: Int,
+                                width: Int,
+                                height: Int
+                            ) {
+                                // NO-OP
+                            }
 
-            scenario.moveToState(Lifecycle.State.RESUMED)
+                            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                                // NO-OP
+                            }
+                        }
+
+                    it.addSurface(it.mSurfaceView, callback)
+                    surfaceView = it.mSurfaceView
+                }
 
             Assert.assertTrue(setupLatch.await(3000, TimeUnit.MILLISECONDS))
             val coords = intArrayOf(0, 0)
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt
index 4a3e5b9..dec948e 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt
@@ -137,9 +137,7 @@
     fun testSurfaceTransactionOnCompleteCallback() {
         val listener = TransactionOnCompleteListener()
 
-        val scenario =
-            ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                .moveToState(Lifecycle.State.CREATED)
+        val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
 
         val destroyLatch = CountDownLatch(1)
         try {
@@ -150,8 +148,6 @@
                     .commit()
             }
 
-            scenario.moveToState(Lifecycle.State.RESUMED)
-
             listener.mLatch.await(3, TimeUnit.SECONDS)
             assertEquals(0, listener.mLatch.count)
             assertTrue(listener.mCallbackTime > 0)
@@ -167,9 +163,7 @@
     fun testSurfaceTransactionOnCommitCallback() {
         val listener = TransactionOnCommitListener()
 
-        val scenario =
-            ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                .moveToState(Lifecycle.State.CREATED)
+        val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
 
         val destroyLatch = CountDownLatch(1)
         try {
@@ -179,7 +173,6 @@
                     .addTransactionCommittedListener(executor!!, listener)
                     .commit()
             }
-            scenario.moveToState(Lifecycle.State.RESUMED)
 
             listener.mLatch.await(3, TimeUnit.SECONDS)
             assertEquals(0, listener.mLatch.count)
@@ -197,9 +190,7 @@
         val listener = TransactionOnCommitListener()
         val listener2 = TransactionOnCommitListener()
 
-        val scenario =
-            ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                .moveToState(Lifecycle.State.CREATED)
+        val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
 
         val destroyLatch = CountDownLatch(1)
         try {
@@ -211,8 +202,6 @@
                     .commit()
             }
 
-            scenario.moveToState(Lifecycle.State.RESUMED)
-
             listener.mLatch.await(3, TimeUnit.SECONDS)
             listener2.mLatch.await(3, TimeUnit.SECONDS)
 
@@ -234,9 +223,7 @@
         val listener1 = TransactionOnCommitListener()
         val listener2 = TransactionOnCompleteListener()
 
-        val scenario =
-            ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                .moveToState(Lifecycle.State.CREATED)
+        val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
 
         val destroyLatch = CountDownLatch(1)
         try {
@@ -248,8 +235,6 @@
                     .commit()
             }
 
-            scenario.moveToState(Lifecycle.State.RESUMED)
-
             listener1.mLatch.await(3, TimeUnit.SECONDS)
             listener2.mLatch.await(3, TimeUnit.SECONDS)
 
@@ -852,39 +837,37 @@
         var scCompat: SurfaceControlWrapper? = null
         val listener = TransactionOnCompleteListener()
         val scenario =
-            ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                .moveToState(Lifecycle.State.CREATED)
-                .onActivity {
-                    val callback =
-                        object : SurfaceHolderCallback() {
-                            override fun surfaceCreated(sh: SurfaceHolder) {
-                                scCompat =
-                                    SurfaceControlWrapper.Builder()
-                                        .setParent(it.getSurfaceView().holder.surface)
-                                        .setDebugName("SurfaceControlCompatTest")
-                                        .build()
+            ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java).onActivity {
+                val callback =
+                    object : SurfaceHolderCallback() {
+                        override fun surfaceCreated(sh: SurfaceHolder) {
+                            scCompat =
+                                SurfaceControlWrapper.Builder()
+                                    .setParent(it.getSurfaceView().holder.surface)
+                                    .setDebugName("SurfaceControlCompatTest")
+                                    .build()
 
-                                // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
-                                val buffer =
-                                    SurfaceControlUtils.getSolidBuffer(
-                                        SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
-                                        SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
-                                        Color.BLUE
-                                    )
+                            // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
+                            val buffer =
+                                SurfaceControlUtils.getSolidBuffer(
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
+                                    Color.BLUE
+                                )
 
-                                SurfaceControlWrapper.Transaction()
-                                    .addTransactionCompletedListener(listener)
-                                    .setBuffer(scCompat!!, buffer)
-                                    .setVisibility(scCompat!!, true)
-                                    .setCrop(scCompat!!, Rect(20, 30, 90, 60))
-                                    .commit()
-                            }
+                            SurfaceControlWrapper.Transaction()
+                                .addTransactionCompletedListener(listener)
+                                .setBuffer(scCompat!!, buffer)
+                                .setVisibility(scCompat!!, true)
+                                .setCrop(scCompat!!, Rect(20, 30, 90, 60))
+                                .commit()
                         }
+                    }
 
-                    it.addSurface(it.mSurfaceView, callback)
-                }
+                it.addSurface(it.mSurfaceView, callback)
+            }
 
-        scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
+        scenario.onActivity {
             assert(listener.mLatch.await(3000, TimeUnit.MILLISECONDS))
             SurfaceControlUtils.validateOutput { bitmap ->
                 val coord = intArrayOf(0, 0)
diff --git a/graphics/graphics-shapes/src/androidInstrumentedTest/kotlin/androidx/graphics/shapes/PolygonTest.kt b/graphics/graphics-shapes/src/androidInstrumentedTest/kotlin/androidx/graphics/shapes/PolygonTest.kt
index 368f7b1..c7f7c75 100644
--- a/graphics/graphics-shapes/src/androidInstrumentedTest/kotlin/androidx/graphics/shapes/PolygonTest.kt
+++ b/graphics/graphics-shapes/src/androidInstrumentedTest/kotlin/androidx/graphics/shapes/PolygonTest.kt
@@ -229,6 +229,29 @@
         }
     }
 
+    @Test
+    fun emptyPolygonTest() {
+        val poly = RoundedPolygon(6, radius = 0f, rounding = CornerRounding(0.1f))
+        assert(poly.cubics.size == 1)
+
+        val stillEmpty = poly.transformed(scaleTransform(10f, 20f))
+        assert(stillEmpty.cubics.size == 1)
+        assert(stillEmpty.cubics.first().zeroLength())
+    }
+
+    @Test
+    fun emptySideTest() {
+        val poly1 =
+            RoundedPolygon(
+                floatArrayOf(0f, 0f, 1f, 0f, 1f, 0f, 0f, 1f), // Triangle with one point repeated
+            )
+        val poly2 =
+            RoundedPolygon(
+                floatArrayOf(0f, 0f, 1f, 0f, 0f, 1f), // Triangle
+            )
+        assertCubicListsEqualish(poly1.cubics, poly2.cubics)
+    }
+
     private fun nonzeroCubics(original: List<Cubic>): List<Cubic> {
         val result = mutableListOf<Cubic>()
         for (i in original.indices) {
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt
index 051588a..5ada39e 100644
--- a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt
@@ -74,7 +74,7 @@
                 }
             }
         }
-        if (lastCubic != null && firstCubic != null)
+        if (lastCubic != null && firstCubic != null) {
             add(
                 Cubic(
                     lastCubic.anchor0X,
@@ -87,6 +87,21 @@
                     firstCubic.anchor0Y
                 )
             )
+        } else {
+            // Empty / 0-sized polygon.
+            add(
+                Cubic(
+                    centerX,
+                    centerY,
+                    centerX,
+                    centerY,
+                    centerX,
+                    centerY,
+                    centerX,
+                    centerY,
+                )
+            )
+        }
     }
 
     init {
@@ -100,12 +115,11 @@
                     abs(cubic.anchor0Y - prevCubic.anchor1Y) > DistanceEpsilon
             ) {
                 debugLog("RoundedPolygon") {
-                    "Ix: $index | (${cubic.anchor0X},${cubic.anchor0Y}) vs " + "$prevCubic"
+                    "Ix: $index | (${cubic.anchor0X},${cubic.anchor0Y}) vs $prevCubic"
                 }
                 throw IllegalArgumentException(
-                    "RoundedPolygon must be contiguous, with the " +
-                        "anchor points of all curves matching the anchor points of the preceding " +
-                        "and succeeding cubics"
+                    "RoundedPolygon must be contiguous, with the anchor points of all curves " +
+                        "matching the anchor points of the preceding and succeeding cubics"
                 )
             }
             prevCubic = cubic
@@ -483,27 +497,51 @@
     val p2: Point,
     val rounding: CornerRounding? = null
 ) {
-    val d1 = (p0 - p1).getDirection()
-    val d2 = (p2 - p1).getDirection()
-    val cornerRadius = rounding?.radius ?: 0f
-    val smoothing = rounding?.smoothing ?: 0f
+    val d1: Point
+    val d2: Point
+    val cornerRadius: Float
+    val smoothing: Float
+    val cosAngle: Float
+    val sinAngle: Float
+    val expectedRoundCut: Float
 
-    // cosine of angle at p1 is dot product of unit vectors to the other two vertices
-    val cosAngle = d1.dotProduct(d2)
+    init {
+        val v01 = p0 - p1
+        val v21 = p2 - p1
+        val d01 = v01.getDistance()
+        val d21 = v21.getDistance()
+        if (d01 > 0f && d21 > 0f) {
+            d1 = v01 / d01
+            d2 = v21 / d21
+            cornerRadius = rounding?.radius ?: 0f
+            smoothing = rounding?.smoothing ?: 0f
 
-    // identity: sin^2 + cos^2 = 1
-    // sinAngle gives us the intersection
-    val sinAngle = sqrt(1 - square(cosAngle))
+            // cosine of angle at p1 is dot product of unit vectors to the other two vertices
+            cosAngle = d1.dotProduct(d2)
 
-    // How much we need to cut, as measured on a side, to get the required radius
-    // calculating where the rounding circle hits the edge
-    // This uses the identity of tan(A/2) = sinA/(1 + cosA), where tan(A/2) = radius/cut
-    val expectedRoundCut =
-        if (sinAngle > 1e-3) {
-            cornerRadius * (cosAngle + 1) / sinAngle
+            // identity: sin^2 + cos^2 = 1
+            // sinAngle gives us the intersection
+            sinAngle = sqrt(1 - square(cosAngle))
+            // How much we need to cut, as measured on a side, to get the required radius
+            // calculating where the rounding circle hits the edge
+            // This uses the identity of tan(A/2) = sinA/(1 + cosA), where tan(A/2) = radius/cut
+            expectedRoundCut =
+                if (sinAngle > 1e-3) {
+                    cornerRadius * (cosAngle + 1) / sinAngle
+                } else {
+                    0f
+                }
         } else {
-            0f
+            // One (or both) of the sides is empty, not much we can do.
+            d1 = Point(0f, 0f)
+            d2 = Point(0f, 0f)
+            cornerRadius = 0f
+            smoothing = 0f
+            cosAngle = 0f
+            sinAngle = 0f
+            expectedRoundCut = 0f
         }
+    }
 
     // smoothing changes the actual cut. 0 is same as expectedRoundCut, 1 doubles it
     val expectedCut: Float
diff --git a/hilt/hilt-compiler/build.gradle b/hilt/hilt-compiler/build.gradle
index 3213852..339bafd 100644
--- a/hilt/hilt-compiler/build.gradle
+++ b/hilt/hilt-compiler/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.SdkHelperKt
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -68,4 +70,5 @@
     mavenVersion = LibraryVersions.HILT
     inceptionYear = "2020"
     description = "AndroidX Hilt Extension Compiler"
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/hilt/hilt-navigation-compose/build.gradle b/hilt/hilt-navigation-compose/build.gradle
index 0d2dbc8..7a73f47 100644
--- a/hilt/hilt-navigation-compose/build.gradle
+++ b/hilt/hilt-navigation-compose/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -78,4 +80,5 @@
     description = "Navigation Compose Hilt Integration"
     legacyDisableKotlinStrictApiMode = true
     samples(projectOrArtifact(":hilt:hilt-navigation-compose-samples"))
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/hilt/hilt-navigation-compose/samples/build.gradle b/hilt/hilt-navigation-compose/samples/build.gradle
index cb0491f..c59ff49 100644
--- a/hilt/hilt-navigation-compose/samples/build.gradle
+++ b/hilt/hilt-navigation-compose/samples/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.Publish
 
@@ -44,6 +46,7 @@
     mavenVersion = LibraryVersions.HILT_NAVIGATION_COMPOSE
     inceptionYear = "2021"
     description = "Samples for the Navigation Compose Hilt Integration"
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 android {
diff --git a/hilt/hilt-navigation-fragment/build.gradle b/hilt/hilt-navigation-fragment/build.gradle
index 5dc55cc1..c78ad99 100644
--- a/hilt/hilt-navigation-fragment/build.gradle
+++ b/hilt/hilt-navigation-fragment/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -69,4 +71,5 @@
     inceptionYear = "2021"
     description = "Android Navigation Fragment Hilt Extension"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/hilt/hilt-navigation/build.gradle b/hilt/hilt-navigation/build.gradle
index 2e4f65b..6ce18e5 100644
--- a/hilt/hilt-navigation/build.gradle
+++ b/hilt/hilt-navigation/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -45,6 +47,7 @@
     inceptionYear = "2021"
     description = "Android Navigation Hilt Extension"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 android {
diff --git a/libraryversions.toml b/libraryversions.toml
index b33669b..3980454 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -21,7 +21,7 @@
 COLLECTION = "1.5.0-alpha01"
 COMPOSE = "1.8.0-alpha01"
 COMPOSE_MATERIAL3 = "1.4.0-alpha01"
-COMPOSE_MATERIAL3_ADAPTIVE = "1.1.0-alpha01"
+COMPOSE_MATERIAL3_ADAPTIVE = "1.1.0-alpha02"
 COMPOSE_MATERIAL3_COMMON = "1.0.0-alpha01"
 COMPOSE_RUNTIME_TRACING = "1.0.0-beta01"
 CONSTRAINTLAYOUT = "2.2.0-beta01"
@@ -43,7 +43,7 @@
 CORE_SPLASHSCREEN = "1.2.0-alpha02"
 CORE_TELECOM = "1.0.0-alpha4"
 CORE_UWB = "1.0.0-alpha08"
-CREDENTIALS = "1.5.0-alpha04"
+CREDENTIALS = "1.5.0-alpha05"
 CREDENTIALS_E2EE_QUARANTINE = "1.0.0-alpha02"
 CREDENTIALS_FIDO_QUARANTINE = "1.0.0-alpha02"
 CURSORADAPTER = "1.1.0-alpha01"
@@ -111,7 +111,7 @@
 PRIVACYSANDBOX_UI = "1.0.0-alpha09"
 PROFILEINSTALLER = "1.4.0-rc01"
 RECOMMENDATION = "1.1.0-alpha01"
-RECYCLERVIEW = "1.4.0-beta01"
+RECYCLERVIEW = "1.4.0-rc01"
 RECYCLERVIEW_SELECTION = "1.2.0-alpha02"
 REMOTECALLBACK = "1.0.0-alpha02"
 RESOURCEINSPECTION = "1.1.0-alpha01"
diff --git a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
index 317bd03..4799f00 100644
--- a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
@@ -83,9 +83,10 @@
                     RestrictToDetector.RESTRICTED,
                     ObsoleteCompatDetector.ISSUE,
                     ReplaceWithDetector.ISSUE,
-                    // This issue is only enabled when `-Pandroidx.migrateArrayAnnotations=true`.
-                    ArrayNullnessMigration.ISSUE,
+                    // This issue is only enabled when `-Pandroidx.useJSpecifyAnnotations=true`.
+                    JSpecifyNullnessMigration.ISSUE,
                     TypeMirrorToString.ISSUE,
+                    BanNullMarked.ISSUE,
                 )
             }
     }
diff --git a/lint-checks/src/main/java/androidx/build/lint/ArrayNullnessMigration.kt b/lint-checks/src/main/java/androidx/build/lint/ArrayNullnessMigration.kt
deleted file mode 100644
index 7e741be..0000000
--- a/lint-checks/src/main/java/androidx/build/lint/ArrayNullnessMigration.kt
+++ /dev/null
@@ -1,184 +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.build.lint
-
-import com.android.tools.lint.client.api.UElementHandler
-import com.android.tools.lint.detector.api.Category
-import com.android.tools.lint.detector.api.Detector
-import com.android.tools.lint.detector.api.Implementation
-import com.android.tools.lint.detector.api.Incident
-import com.android.tools.lint.detector.api.Issue
-import com.android.tools.lint.detector.api.JavaContext
-import com.android.tools.lint.detector.api.Location
-import com.android.tools.lint.detector.api.Scope
-import com.android.tools.lint.detector.api.Severity
-import com.android.tools.lint.detector.api.isKotlin
-import com.intellij.psi.PsiArrayType
-import com.intellij.psi.PsiEllipsisType
-import java.util.EnumSet
-import org.jetbrains.uast.UAnnotation
-import org.jetbrains.uast.UElement
-import org.jetbrains.uast.UField
-import org.jetbrains.uast.UMethod
-import org.jetbrains.uast.UParameter
-
-/**
- * Repositions nullness annotations on arrays to facilitate migrating the nullness annotations to
- * TYPE_USE. See the issue description in the companion object for more detail.
- */
-class ArrayNullnessMigration : Detector(), Detector.UastScanner {
-    override fun getApplicableUastTypes() = listOf(UAnnotation::class.java)
-
-    override fun createUastHandler(context: JavaContext): UElementHandler {
-        return AnnotationChecker(context)
-    }
-
-    private inner class AnnotationChecker(val context: JavaContext) : UElementHandler() {
-        override fun visitAnnotation(node: UAnnotation) {
-            // Nullness annotations are only relevant for Java source.
-            if (isKotlin(node.lang)) return
-
-            // Verify this is a nullness annotation.
-            val annotationName = node.qualifiedName ?: return
-            if (annotationName !in nullnessAnnotations) return
-
-            // Find the type of the annotated element, and only continue if it is an array.
-            val annotated = node.uastParent ?: return
-            val type =
-                when (annotated) {
-                    is UParameter -> annotated.type
-                    is UMethod -> annotated.returnType
-                    is UField -> annotated.type
-                    else -> return
-                }
-            if (type !is PsiArrayType) return
-
-            // Determine the file location for the autofix. This is a bit complicated because it
-            // needs to avoid editing the wrong thing, like the doc comment preceding a method, but
-            // also is doing some reformatting in the area around the annotation.
-            // This is where the annotation itself is located.
-            val annotationLocation = context.getLocation(node)
-            // This is where the element being annotated is located.
-            val annotatedLocation = context.getLocation(annotated as UElement)
-            // If the annotation and annotated element aren't on the same line, that probably means
-            // the annotation is on its own line, with indentation before it. To also get rid of
-            // that indentation, start the range at the start of the annotation's line.
-            // If the annotation and annotated element are on the same line, just start at the
-            // annotation starting place to avoid including e.g. other parameters.
-            val startLocation =
-                if (annotatedLocation.start!!.sameLine(annotationLocation.start!!)) {
-                    annotationLocation.start!!
-                } else {
-                    Location.create(
-                            context.file,
-                            context.getContents()!!.toString(),
-                            annotationLocation.start!!.line
-                        )
-                        .start!!
-                }
-            val fixLocation =
-                Location.create(annotatedLocation.file, startLocation, annotatedLocation.end)
-
-            // Part 1 of the fix: remove the original annotation
-            val annotationString = node.asSourceString()
-            val removeOriginalAnnotation =
-                fix()
-                    .replace()
-                    .range(fixLocation)
-                    // In addition to the annotation, also remove any extra whitespace and trailing
-                    // new line. The reformat option unfortunately doesn't do this.
-                    .pattern("((    )*$annotationString ?\n?)")
-                    .with("")
-                    // Only remove one instance of the annotation.
-                    .repeatedly(false)
-                    .autoFix()
-                    .build()
-
-            // Vararg types are also arrays, determine which array marker is present here.
-            val arraySuffix =
-                if (type is PsiEllipsisType) {
-                    "..."
-                } else {
-                    "[]"
-                }
-            // Part 2 of the fix: add a new annotation.
-            val addNewAnnotation =
-                fix()
-                    .replace()
-                    .range(fixLocation)
-                    .text(arraySuffix)
-                    .with(" $annotationString $arraySuffix")
-                    // Only add one instance of the annotation. This will replace the first instance
-                    // of []/..., which is correct. In `String @Nullable [][]` the annotation
-                    // applies to the outer `String[][]` type, while in `String[] @Nullable []` it
-                    // applies to the inner `String[]` arrays.
-                    .repeatedly(false)
-                    .autoFix()
-                    .build()
-
-            // Combine the two elements of the fix and report.
-            val fix =
-                fix()
-                    .name("Move annotation")
-                    .composite()
-                    .add(removeOriginalAnnotation)
-                    .add(addNewAnnotation)
-                    .autoFix()
-                    .build()
-
-            val incident =
-                Incident(context)
-                    .message("Nullness annotation on array will apply to element")
-                    .issue(ISSUE)
-                    .location(context.getLocation(annotated as UElement))
-                    .scope(annotated)
-                    .fix(fix)
-            context.report(incident)
-        }
-    }
-
-    companion object {
-        val nullnessAnnotations =
-            listOf(
-                "androidx.annotation.NonNull",
-                "androidx.annotation.Nullable",
-            )
-        val ISSUE =
-            Issue.create(
-                "ArrayMigration",
-                "Migrate arrays to type-use nullness annotations",
-                """
-                    When nullness annotations do not target TYPE_USE, the following definition means
-                    that the type of `arg` is nullable:
-                        @Nullable String[] arg
-                    However, if the annotation targets TYPE_USE, it now applies to the component
-                    type of the array, meaning that `arg`'s type is an array of nullable strings.
-                    To retain the original meaning, the definition needs to be changed to this:
-                        String @Nullable [] arg
-                    This check performs that migration to enable converting nullness annotations to
-                    target TYPE_USE.
-                """,
-                Category.CORRECTNESS,
-                5,
-                Severity.ERROR,
-                Implementation(
-                    ArrayNullnessMigration::class.java,
-                    EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
-                )
-            )
-    }
-}
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanNullMarked.kt b/lint-checks/src/main/java/androidx/build/lint/BanNullMarked.kt
new file mode 100644
index 0000000..9b735cc
--- /dev/null
+++ b/lint-checks/src/main/java/androidx/build/lint/BanNullMarked.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.build.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import org.jetbrains.uast.UAnnotation
+
+class BanNullMarked : Detector(), Detector.UastScanner {
+
+    override fun getApplicableUastTypes() = listOf(UAnnotation::class.java)
+
+    override fun createUastHandler(context: JavaContext): UElementHandler {
+        return AnnotationChecker(context)
+    }
+
+    private inner class AnnotationChecker(val context: JavaContext) : UElementHandler() {
+        override fun visitAnnotation(node: UAnnotation) {
+            if (node.qualifiedName != "org.jspecify.annotations.NullMarked") return
+
+            val incident =
+                Incident(context)
+                    .issue(ISSUE)
+                    .location(context.getLocation(node))
+                    .scope(node)
+                    .message("Should not use @NullMarked annotation")
+            context.report(incident)
+        }
+    }
+
+    companion object {
+        val ISSUE =
+            Issue.create(
+                "BanNullMarked",
+                "Should not use @NullMarked annotation",
+                "Usage of the @NullMarked annotation is not allowed because lint and metalava do not support it",
+                Category.CORRECTNESS,
+                5,
+                Severity.ERROR,
+                Implementation(BanNullMarked::class.java, Scope.JAVA_FILE_SCOPE)
+            )
+    }
+}
diff --git a/lint-checks/src/main/java/androidx/build/lint/JSpecifyNullnessMigration.kt b/lint-checks/src/main/java/androidx/build/lint/JSpecifyNullnessMigration.kt
new file mode 100644
index 0000000..a57fe59
--- /dev/null
+++ b/lint-checks/src/main/java/androidx/build/lint/JSpecifyNullnessMigration.kt
@@ -0,0 +1,221 @@
+/*
+ * 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.build.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.LintFix
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.isKotlin
+import com.intellij.psi.PsiArrayType
+import com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiEllipsisType
+import com.intellij.psi.PsiPrimitiveType
+import java.util.EnumSet
+import org.jetbrains.uast.UAnnotation
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UField
+import org.jetbrains.uast.ULocalVariable
+import org.jetbrains.uast.UMethod
+import org.jetbrains.uast.UParameter
+
+/**
+ * Repositions nullness annotations to facilitate migrating the nullness annotations to JSpecify
+ * TYPE_USE annotations. See the issue description in the companion object for more detail.
+ */
+class JSpecifyNullnessMigration : Detector(), Detector.UastScanner {
+    override fun getApplicableUastTypes() = listOf(UAnnotation::class.java)
+
+    override fun createUastHandler(context: JavaContext): UElementHandler {
+        return AnnotationChecker(context)
+    }
+
+    private inner class AnnotationChecker(val context: JavaContext) : UElementHandler() {
+        override fun visitAnnotation(node: UAnnotation) {
+            // Nullness annotations are only relevant for Java source.
+            if (isKotlin(node.lang)) return
+
+            // Verify this is a nullness annotation.
+            val annotationName = node.qualifiedName ?: return
+            if (annotationName !in nullnessAnnotations.keys) return
+            val replacementAnnotationName = nullnessAnnotations[annotationName]!!
+
+            val fix = createFix(node, replacementAnnotationName)
+            val incident =
+                Incident(context)
+                    .message("Switch nullness annotation to JSpecify")
+                    .issue(ISSUE)
+                    .location(context.getLocation(node as UElement))
+                    .scope(node)
+                    .fix(fix)
+            context.report(incident)
+        }
+
+        fun createFix(node: UAnnotation, replacementAnnotationName: String): LintFix? {
+            // Find the type of the annotated element.
+            val annotated = node.uastParent ?: return null
+            val type =
+                when (annotated) {
+                    is UParameter -> annotated.type
+                    is UMethod -> annotated.returnType
+                    is UField -> annotated.type
+                    is ULocalVariable -> annotated.type
+                    else -> return null
+                } ?: return null
+
+            // Determine the file location for the autofix. This is a bit complicated because it
+            // needs to avoid editing the wrong thing, like the doc comment preceding a method, but
+            // also is doing some reformatting in the area around the annotation.
+            // This is where the annotation itself is located.
+            val annotationLocation = context.getLocation(node)
+            // This is where the element being annotated is located.
+            val annotatedLocation = context.getLocation(annotated as UElement)
+            // If the annotation and annotated element aren't on the same line, that probably means
+            // the annotation is on its own line, with indentation before it. To also get rid of
+            // that indentation, start the range at the start of the annotation's line.
+            // If the annotation and annotated element are on the same line, just start at the
+            // annotation starting place to avoid including e.g. other parameters.
+            val annotatedStart = annotatedLocation.start ?: return null
+            val annotationStart = annotationLocation.start ?: return null
+            val startLocation =
+                if (annotatedStart.sameLine(annotationStart)) {
+                    annotationStart
+                } else {
+                    Location.create(
+                            context.file,
+                            context.getContents()!!.toString(),
+                            annotationStart.line
+                        )
+                        .start!!
+                }
+            val fixLocation =
+                Location.create(annotatedLocation.file, startLocation, annotatedLocation.end)
+
+            // Part 1 of the fix: remove the original annotation
+            val annotationString = node.asSourceString()
+            val removeOriginalAnnotation =
+                fix()
+                    .replace()
+                    .range(fixLocation)
+                    // In addition to the annotation, also remove any extra whitespace and trailing
+                    // new line. The reformat option unfortunately doesn't do this.
+                    .pattern("((    )*$annotationString ?\n?)")
+                    .with("")
+                    // Only remove one instance of the annotation.
+                    .repeatedly(false)
+                    .autoFix()
+                    .build()
+
+            // The jspecify annotations can't be applied to primitive types (since primitives are
+            // non-null by definition) or local variables, so just remove the annotation in those
+            // cases. For all other cases, also add a new annotation to the correct position.
+            return if (type is PsiPrimitiveType || annotated is ULocalVariable) {
+                removeOriginalAnnotation
+            } else {
+                // Create a regex pattern for where to insert the annotation. The replacement lint
+                // removes the first capture group (section in parentheses) of the supplied regex.
+                // Since this fix is really just to insert an annotation, use an empty capture group
+                // so nothing is removed.
+                val (prefix, textToReplace) =
+                    when {
+                        // For a vararg type where the component type is an array, the annotation
+                        // goes before the array instead of the vararg ("String @NonNull []..."),
+                        // so only match the "..." when the component isn't an array.
+                        type is PsiEllipsisType && type.componentType !is PsiArrayType ->
+                            Pair(" ", "()\\.\\.\\.")
+                        type is PsiArrayType -> Pair(" ", "()\\[\\]")
+                        // Make sure to match the right usage of the class name: find the name
+                        // preceded by a space or dot, and followed by a space, open angle bracket,
+                        // or newline character.
+                        type is PsiClassType -> Pair("", "[ .]()${type.className}[ <\\n\\r]")
+                        else -> Pair("", "()${type.presentableText}")
+                    }
+                val replacement = "$prefix@$replacementAnnotationName "
+
+                // Part 2 of the fix: add a new annotation.
+                val addNewAnnotation =
+                    fix()
+                        .replace()
+                        .range(fixLocation)
+                        .pattern(textToReplace)
+                        .with(replacement)
+                        // Only add one instance of the annotation. For nested array types, this
+                        // will replace the first instance of []/..., which is correct. In
+                        // `String @Nullable [][]` the annotation applies to the outer `String[][]`
+                        // type, while in `String[] @Nullable []` it applies to the inner `String[]`
+                        // arrays.
+                        .repeatedly(false)
+                        .shortenNames()
+                        .autoFix()
+                        .build()
+
+                // Combine the two elements of the fix.
+                return fix()
+                    .name("Move annotation")
+                    .composite()
+                    .add(removeOriginalAnnotation)
+                    .add(addNewAnnotation)
+                    .autoFix()
+                    .build()
+            }
+        }
+    }
+
+    companion object {
+        val nullnessAnnotations =
+            mapOf(
+                "androidx.annotation.NonNull" to "NonNull",
+                "androidx.annotation.Nullable" to "Nullable",
+            )
+        val ISSUE =
+            Issue.create(
+                "JSpecifyNullness",
+                "Migrate nullness annotations to type-use position",
+                """
+                    Switches from AndroidX nullness annotations to JSpecify, which are type-use.
+                    Type-use annotations have different syntactic positions than non-type-use
+                    annotations in some cases.
+
+                    For instance, when nullness annotations do not target TYPE_USE, the following
+                    definition means that the type of `arg` is nullable:
+                        @Nullable String[] arg
+                    However, if the annotation targets TYPE_USE, it now applies to the component
+                    type of the array, meaning that `arg`'s type is an array of nullable strings.
+                    To retain the original meaning, the definition needs to be changed to this:
+                        String @Nullable [] arg
+
+                    Type-use nullness annotations must go before the simple class name of a
+                    qualified type. For instance, `java.lang.@Nullable String` is required instead
+                    of `@Nullable java.lang.String`.
+                """,
+                Category.CORRECTNESS,
+                5,
+                Severity.ERROR,
+                Implementation(
+                    JSpecifyNullnessMigration::class.java,
+                    EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
+                )
+            )
+    }
+}
diff --git a/lint-checks/src/test/java/androidx/build/lint/ArrayNullnessMigrationTest.kt b/lint-checks/src/test/java/androidx/build/lint/ArrayNullnessMigrationTest.kt
deleted file mode 100644
index 556cf75..0000000
--- a/lint-checks/src/test/java/androidx/build/lint/ArrayNullnessMigrationTest.kt
+++ /dev/null
@@ -1,359 +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.build.lint
-
-import com.android.tools.lint.checks.infrastructure.TestFile
-import com.android.tools.lint.checks.infrastructure.TestMode
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ArrayNullnessMigrationTest :
-    AbstractLintDetectorTest(
-        useDetector = ArrayNullnessMigration(),
-        useIssues = listOf(ArrayNullnessMigration.ISSUE),
-        stubs = annotationStubs
-    ) {
-    @Test
-    fun `Nullness annotation on parameter`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.NonNull;
-                public class Foo {
-                    public void foo(@NonNull String[] arr) {}
-                }
-                """
-                    .trimIndent()
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:4: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public void foo(@NonNull String[] arr) {}
-                                ~~~~~~~~~~~~~~~~~~~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
-            @@ -4 +4
-            -     public void foo(@NonNull String[] arr) {}
-            +     public void foo(String @NonNull [] arr) {}
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on method return`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.Nullable;
-                public class Foo {
-                    @Nullable
-                    public String[] foo() { return null; }
-                }
-                """
-                    .trimIndent(),
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:5: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public String[] foo() { return null; }
-                                ~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 5: Move annotation:
-            @@ -4 +4
-            -     @Nullable
-            -     public String[] foo() { return null; }
-            +     public String @Nullable [] foo() { return null; }
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on method return and parameter`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.Nullable;
-                public class Foo {
-                    @Nullable
-                    public String[] foo(@Nullable String[] arr) { return null; }
-                }
-                """
-                    .trimIndent()
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:5: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public String[] foo(@Nullable String[] arr) { return null; }
-                                ~~~
-            src/test/pkg/Foo.java:5: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public String[] foo(@Nullable String[] arr) { return null; }
-                                    ~~~~~~~~~~~~~~~~~~~~~~
-            2 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 5: Move annotation:
-            @@ -4 +4
-            -     @Nullable
-            -     public String[] foo(@Nullable String[] arr) { return null; }
-            +     public String @Nullable [] foo(@Nullable String[] arr) { return null; }
-            Autofix for src/test/pkg/Foo.java line 5: Move annotation:
-            @@ -5 +5
-            -     public String[] foo(@Nullable String[] arr) { return null; }
-            +     public String[] foo(String @Nullable [] arr) { return null; }
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on field`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.Nullable;
-                public class Foo {
-                    @Nullable public String[] foo;
-                }
-                """
-                    .trimIndent()
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:4: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                @Nullable public String[] foo;
-                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
-            @@ -4 +4
-            -     @Nullable public String[] foo;
-            +     public String @Nullable [] foo;
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on 2d array`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.Nullable;
-                public class Foo {
-                    @Nullable public String[][] foo;
-                }
-                """
-                    .trimIndent()
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:4: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                @Nullable public String[][] foo;
-                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
-            @@ -4 +4
-            -     @Nullable public String[][] foo;
-            +     public String @Nullable [][] foo;
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on varargs`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.NonNull;
-                public class Foo {
-                    public void foo(@NonNull String... arr) {}
-                }
-                """
-                    .trimIndent(),
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:4: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public void foo(@NonNull String... arr) {}
-                                ~~~~~~~~~~~~~~~~~~~~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
-            @@ -4 +4
-            -     public void foo(@NonNull String... arr) {}
-            +     public void foo(String @NonNull ... arr) {}
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on method return with array in comments`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.Nullable;
-                public class Foo {
-                   /**
-                    * @return A String[]
-                    */
-                    @Nullable
-                    public String[] foo() { return null; }
-                }
-                """
-                    .trimIndent(),
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:8: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public String[] foo() { return null; }
-                                ~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 8: Move annotation:
-            @@ -7 +7
-            -     @Nullable
-            -     public String[] foo() { return null; }
-            +     public String @Nullable [] foo() { return null; }
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    @Test
-    fun `Nullness annotation on method return with annotation in comments`() {
-        val input =
-            java(
-                """
-                package test.pkg;
-                import androidx.annotation.Nullable;
-                public class Foo {
-                   /**
-                    * @return A @Nullable string array
-                    */
-                    @Nullable
-                    public String[] foo() { return null; }
-                }
-                """
-                    .trimIndent(),
-            )
-
-        val expected =
-            """
-            src/test/pkg/Foo.java:8: Error: Nullness annotation on array will apply to element [ArrayMigration]
-                public String[] foo() { return null; }
-                                ~~~
-            1 errors, 0 warnings
-            """
-                .trimIndent()
-
-        val expectedFixDiffs =
-            """
-            Autofix for src/test/pkg/Foo.java line 8: Move annotation:
-            @@ -7 +7
-            -     @Nullable
-            -     public String[] foo() { return null; }
-            +     public String @Nullable [] foo() { return null; }
-            """
-                .trimIndent()
-
-        runArrayNullnessTest(input, expected, expectedFixDiffs)
-    }
-
-    private fun runArrayNullnessTest(input: TestFile, expected: String, expectedFixDiffs: String) {
-        lint()
-            .files(*stubs, input)
-            .skipTestModes(TestMode.WHITESPACE)
-            .run()
-            .expect(expected)
-            .expectFixDiffs(expectedFixDiffs)
-    }
-
-    companion object {
-        val annotationStubs =
-            arrayOf(
-                kotlin(
-                    """
-                        package androidx.annotation
-                        annotation class NonNull
-                    """
-                ),
-                kotlin(
-                    """
-                        package androidx.annotation
-                        annotation class Nullable
-                    """
-                )
-            )
-    }
-}
diff --git a/lint-checks/src/test/java/androidx/build/lint/BanNullMarkedTest.kt b/lint-checks/src/test/java/androidx/build/lint/BanNullMarkedTest.kt
new file mode 100644
index 0000000..c16ea81
--- /dev/null
+++ b/lint-checks/src/test/java/androidx/build/lint/BanNullMarkedTest.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.build.lint
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class BanNullMarkedTest :
+    AbstractLintDetectorTest(
+        useDetector = BanNullMarked(),
+        useIssues = listOf(BanNullMarked.ISSUE),
+        stubs = arrayOf(nullMarkedStub)
+    ) {
+    @Test
+    fun `Usage of NullMarked in a package-info file`() {
+        val input =
+            java(
+                """
+                    @NullMarked
+                    package test.pkg;
+
+                    import org.jspecify.annotations.NullMarked;
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/package-info.java:1: Error: Should not use @NullMarked annotation [BanNullMarked]
+                @NullMarked
+                ~~~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        check(input).expect(expected)
+    }
+
+    @Test
+    fun `Usage of NullMarked on a class`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+
+                    import org.jspecify.annotations.NullMarked;
+
+                    @NullMarked
+                    public class Foo {}
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:5: Error: Should not use @NullMarked annotation [BanNullMarked]
+                @NullMarked
+                ~~~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        check(input).expect(expected)
+    }
+
+    @Test
+    fun `Usage of NullMarked on a method`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+
+                    import org.jspecify.annotations.NullMarked;
+
+                    public class Foo {
+                        @NullMarked
+                        public void foo() {}
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:6: Error: Should not use @NullMarked annotation [BanNullMarked]
+                    @NullMarked
+                    ~~~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        check(input).expect(expected)
+    }
+
+    @Test
+    fun `Usage of NullMarked on a constructor`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+
+                    import org.jspecify.annotations.NullMarked;
+
+                    public class Foo {
+                        @NullMarked
+                        public Foo() {}
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:6: Error: Should not use @NullMarked annotation [BanNullMarked]
+                    @NullMarked
+                    ~~~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        check(input).expect(expected)
+    }
+
+    companion object {
+        private val nullMarkedStub =
+            java(
+                """
+                    package org.jspecify.annotations;
+
+                    import java.lang.annotation.ElementType;
+                    import java.lang.annotation.Target;
+
+                    @Target({ElementType.MODULE, ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
+                    public @interface NullMarked {}
+                """
+                    .trimIndent()
+            )
+    }
+}
diff --git a/lint-checks/src/test/java/androidx/build/lint/JSpecifyNullnessMigrationTest.kt b/lint-checks/src/test/java/androidx/build/lint/JSpecifyNullnessMigrationTest.kt
new file mode 100644
index 0000000..2b91a0a
--- /dev/null
+++ b/lint-checks/src/test/java/androidx/build/lint/JSpecifyNullnessMigrationTest.kt
@@ -0,0 +1,790 @@
+/*
+ * 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.build.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestMode
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class JSpecifyNullnessMigrationTest :
+    AbstractLintDetectorTest(
+        useDetector = JSpecifyNullnessMigration(),
+        useIssues = listOf(JSpecifyNullnessMigration.ISSUE),
+        stubs = annotationStubs
+    ) {
+    @Test
+    fun `Nullness annotation on array parameter`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.NonNull;
+                public class Foo {
+                    public void foo(@NonNull String[] arr) {}
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                public void foo(@NonNull String[] arr) {}
+                                ~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+            @@ -4 +4
+            -     public void foo(@NonNull String[] arr) {}
+            +     public void foo(String @NonNull [] arr) {}
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on array method return`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    @Nullable
+                    public String[] foo() { return null; }
+                }
+                """
+                    .trimIndent(),
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable
+                ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+            @@ -4 +4
+            -     @Nullable
+            -     public String[] foo() { return null; }
+            +     public String @Nullable [] foo() { return null; }
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on array method return and array parameter`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    @Nullable
+                    public String[] foo(@Nullable String[] arr) { return null; }
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable
+                ~~~~~~~~~
+            src/test/pkg/Foo.java:5: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                public String[] foo(@Nullable String[] arr) { return null; }
+                                    ~~~~~~~~~
+            2 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+            @@ -4 +4
+            -     @Nullable
+            -     public String[] foo(@Nullable String[] arr) { return null; }
+            +     public String @Nullable [] foo(@Nullable String[] arr) { return null; }
+            Autofix for src/test/pkg/Foo.java line 5: Move annotation:
+            @@ -5 +5
+            -     public String[] foo(@Nullable String[] arr) { return null; }
+            +     public String[] foo(String @Nullable [] arr) { return null; }
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on array field`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    @Nullable public String[] foo;
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable public String[] foo;
+                ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+            @@ -4 +4
+            -     @Nullable public String[] foo;
+            +     public String @Nullable [] foo;
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on 2d array`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    @Nullable public String[][] foo;
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable public String[][] foo;
+                ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+            @@ -4 +4
+            -     @Nullable public String[][] foo;
+            +     public String @Nullable [][] foo;
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on varargs`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.NonNull;
+                public class Foo {
+                    public void foo(@NonNull String... arr) {}
+                }
+                """
+                    .trimIndent(),
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                public void foo(@NonNull String... arr) {}
+                                ~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+            @@ -4 +4
+            -     public void foo(@NonNull String... arr) {}
+            +     public void foo(String @NonNull ... arr) {}
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on array varargs`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.NonNull;
+                    public class Foo {
+                        public void foo(@NonNull String[]... args) {}
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    public void foo(@NonNull String[]... args) {}
+                                    ~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+                @@ -4 +4
+                -     public void foo(@NonNull String[]... args) {}
+                +     public void foo(String @NonNull []... args) {}
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on method return with array in comments`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                   /**
+                    * @return A String[]
+                    */
+                    @Nullable
+                    public String[] foo() { return null; }
+                }
+                """
+                    .trimIndent(),
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:7: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable
+                ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 7: Move annotation:
+            @@ -7 +7
+            -     @Nullable
+            -     public String[] foo() { return null; }
+            +     public String @Nullable [] foo() { return null; }
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on method return with annotation in comments`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                   /**
+                    * @return A @Nullable string array
+                    */
+                    @Nullable
+                    public String[] foo() { return null; }
+                }
+                """
+                    .trimIndent(),
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:7: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable
+                ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 7: Move annotation:
+            @@ -7 +7
+            -     @Nullable
+            -     public String[] foo() { return null; }
+            +     public String @Nullable [] foo() { return null; }
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation removed from local variable declaration`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.Nullable;
+                    public class Foo {
+                        public String foo() {
+                            @Nullable String str = null;
+                            return str;
+                        }
+                    }
+                """
+                    .trimIndent()
+            )
+        val expected =
+            """
+            src/test/pkg/Foo.java:5: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    @Nullable String str = null;
+                    ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+        val expectedFixDiffs =
+            """
+            Autofix for src/test/pkg/Foo.java line 5: Delete:
+            @@ -5 +5
+            -         @Nullable String str = null;
+            +         String str = null;
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation removed from void return type`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.Nullable;
+                    public class Foo {
+                        @Nullable
+                        public void foo() {}
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    @Nullable
+                    ~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 4: Delete:
+                @@ -4 +4
+                -     @Nullable
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation removed from primitive parameter type`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.Nullable;
+                    public class Foo {
+                        public void foo(@Nullable int i) {}
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    public void foo(@Nullable int i) {}
+                                    ~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 4: Delete:
+                @@ -4 +4
+                -     public void foo(@Nullable int i) {}
+                +     public void foo(int i) {}
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on class type parameter`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.NonNull;
+                public class Foo {
+                    public void foo(@NonNull Foo.InnerFoo arr) {}
+                    public class InnerFoo {}
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                public void foo(@NonNull Foo.InnerFoo arr) {}
+                                ~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+                @@ -4 +4
+                -     public void foo(@NonNull Foo.InnerFoo arr) {}
+                +     public void foo(Foo.@NonNull InnerFoo arr) {}
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on class type return`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    @Nullable
+                    public String foo() { return null; }
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable
+                ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+                @@ -4 +4
+                -     @Nullable
+                -     public String foo() { return null; }
+                +     public @Nullable String foo() { return null; }
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on class type param`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    public String foo(@Nullable String foo) { return null; }
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                public String foo(@Nullable String foo) { return null; }
+                                  ~~~~~~~~~
+            1 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs = ""
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on class type param and return`() {
+        val input =
+            java(
+                """
+                package test.pkg;
+                import androidx.annotation.NonNull;
+                import androidx.annotation.Nullable;
+                public class Foo {
+                    @Nullable
+                    public String foo(@NonNull String foo) { return null; }
+                }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+            src/test/pkg/Foo.java:5: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                @Nullable
+                ~~~~~~~~~
+            src/test/pkg/Foo.java:6: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                public String foo(@NonNull String foo) { return null; }
+                                  ~~~~~~~~
+            2 errors, 0 warnings
+            """
+                .trimIndent()
+
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 5: Move annotation:
+                @@ -5 +5
+                -     @Nullable
+                -     public String foo(@NonNull String foo) { return null; }
+                +     public @Nullable String foo(@NonNull String foo) { return null; }
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on type parameter return`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.Nullable;
+                    public class Foo {
+                        @Nullable
+                        public <T> T foo() {
+                            return null;
+                        }
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    @Nullable
+                    ~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 4: Move annotation:
+                @@ -4 +4
+                -     @Nullable
+                -     public <T> T foo() {
+                +     public <T> @Nullable T foo() {
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on inner type where outer type contains name`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.Nullable;
+                    public class RecyclerView {
+                        public class Recycler {}
+                        @Nullable
+                        public RecyclerView.Recycler foo() {
+                            return null;
+                        }
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/RecyclerView.java:5: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    @Nullable
+                    ~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/RecyclerView.java line 5: Move annotation:
+                @@ -5 +5
+                -     @Nullable
+                -     public RecyclerView.Recycler foo() {
+                +     public RecyclerView.@Nullable Recycler foo() {
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on parameterized type`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.Nullable;
+                    import java.util.List;
+                    public class Foo {
+                        @Nullable
+                        public List<String> foo() {
+                            return null;
+                        }
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:5: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    @Nullable
+                    ~~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+        val expectedFixDiffs =
+            """
+                Autofix for src/test/pkg/Foo.java line 5: Move annotation:
+                @@ -5 +5
+                -     @Nullable
+                -     public List<String> foo() {
+                +     public @Nullable List<String> foo() {
+            """
+                .trimIndent()
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    @Test
+    fun `Nullness annotation on parameter with newline after type`() {
+        val input =
+            java(
+                """
+                    package test.pkg;
+                    import androidx.annotation.NonNull;
+                    public class Foo {
+                        public void foo(@NonNull String
+                            arg) {}
+                    }
+                """
+                    .trimIndent()
+            )
+
+        val expected =
+            """
+                src/test/pkg/Foo.java:4: Error: Switch nullness annotation to JSpecify [JSpecifyNullness]
+                    public void foo(@NonNull String
+                                    ~~~~~~~~
+                1 errors, 0 warnings
+            """
+                .trimIndent()
+        val expectedFixDiffs = ""
+
+        runNullnessTest(input, expected, expectedFixDiffs)
+    }
+
+    private fun runNullnessTest(input: TestFile, expected: String, expectedFixDiffs: String) {
+        lint()
+            .files(*stubs, input)
+            // Skip WHITESPACE mode because an array suffix with whitespace in the middle "[ ]" will
+            // break the pattern matching, but is extremely unlikely to happen in practice.
+            // Skip FULLY_QUALIFIED mode because the type-use annotation positioning depends on
+            // whether types are fully qualified, so fixes will be different.
+            .skipTestModes(TestMode.WHITESPACE, TestMode.FULLY_QUALIFIED)
+            .run()
+            .expect(expected)
+            .expectFixDiffs(expectedFixDiffs)
+    }
+
+    companion object {
+        val annotationStubs =
+            arrayOf(
+                kotlin(
+                    """
+                        package androidx.annotation
+                        annotation class NonNull
+                    """
+                ),
+                kotlin(
+                    """
+                        package androidx.annotation
+                        annotation class Nullable
+                    """
+                )
+            )
+    }
+}
diff --git a/lint/lint-gradle/build.gradle b/lint/lint-gradle/build.gradle
index e578727..2ac0206 100644
--- a/lint/lint-gradle/build.gradle
+++ b/lint/lint-gradle/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.Publish
 
@@ -45,4 +47,5 @@
     publish = Publish.SNAPSHOT_AND_RELEASE
     inceptionYear = "2024"
     description = "Lint checks to verify usage of Gradle APIs."
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/navigation/navigation-common/build.gradle b/navigation/navigation-common/build.gradle
index 7921162..bcde5af 100644
--- a/navigation/navigation-common/build.gradle
+++ b/navigation/navigation-common/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -78,4 +80,5 @@
     inceptionYear = "2017"
     description = "Android Navigation-Common"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle
index 9fa7d67..0088065 100644
--- a/navigation/navigation-compose/build.gradle
+++ b/navigation/navigation-compose/build.gradle
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -68,6 +70,7 @@
     legacyDisableKotlinStrictApiMode = true
     samples(projectOrArtifact(":navigation:navigation-compose:navigation-compose-samples"))
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 android {
diff --git a/navigation/navigation-compose/samples/build.gradle b/navigation/navigation-compose/samples/build.gradle
index 19e494b..b672a68 100644
--- a/navigation/navigation-compose/samples/build.gradle
+++ b/navigation/navigation-compose/samples/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
@@ -52,6 +54,7 @@
     type = LibraryType.SAMPLES
     inceptionYear = "2020"
     description = "Samples for Compose integration with Navigation"
+    kotlinTarget = KotlinTarget.KOTLIN_2_0
 }
 
 tasks.withType(KotlinCompile).configureEach {
diff --git a/navigation/navigation-dynamic-features-fragment/build.gradle b/navigation/navigation-dynamic-features-fragment/build.gradle
index a1527d203..34a65f65 100644
--- a/navigation/navigation-dynamic-features-fragment/build.gradle
+++ b/navigation/navigation-dynamic-features-fragment/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
@@ -68,4 +70,5 @@
     inceptionYear = "2019"
     description = "Android Dynamic Feature Navigation Fragment"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/navigation/navigation-fragment-compose/build.gradle b/navigation/navigation-fragment-compose/build.gradle
index 9b1cc7b..415e042 100644
--- a/navigation/navigation-fragment-compose/build.gradle
+++ b/navigation/navigation-fragment-compose/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -56,4 +58,5 @@
     inceptionYear = "2024"
     description = "Add Compose destinations to Navigation with Fragments"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/navigation/navigation-fragment/build.gradle b/navigation/navigation-fragment/build.gradle
index b20d87a..6c5a89a 100644
--- a/navigation/navigation-fragment/build.gradle
+++ b/navigation/navigation-fragment/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -57,6 +59,7 @@
     inceptionYear = "2017"
     description = "Android Navigation-Fragment"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
 android {
diff --git a/navigation/navigation-lint-common/build.gradle b/navigation/navigation-lint-common/build.gradle
index 4ed49c5..192dd51 100644
--- a/navigation/navigation-lint-common/build.gradle
+++ b/navigation/navigation-lint-common/build.gradle
@@ -31,6 +31,8 @@
 dependencies {
     compileOnly(libs.androidLintMinApi)
     compileOnly(libs.kotlinStdlib)
+    compileOnly(libs.androidLintTests)
+    compileOnly(libs.junit)
 }
 
 androidx {
diff --git a/navigation/navigation-lint-common/src/main/java/androidx/navigation/lint/common/LintUtil.kt b/navigation/navigation-lint-common/src/main/java/androidx/navigation/lint/common/LintUtil.kt
index 611f180..85d67c3 100644
--- a/navigation/navigation-lint-common/src/main/java/androidx/navigation/lint/common/LintUtil.kt
+++ b/navigation/navigation-lint-common/src/main/java/androidx/navigation/lint/common/LintUtil.kt
@@ -16,6 +16,11 @@
 
 package androidx.navigation.lint.common
 
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import java.util.Locale
+import org.intellij.lang.annotations.Language
 import org.jetbrains.kotlin.analysis.api.analyze
 import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
 import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
@@ -66,3 +71,60 @@
             symbol.classKind == KtClassKind.COMPANION_OBJECT) to symbol.name?.asString()
     }
 }
+
+/**
+ * Copied from compose.lint.test.stubs
+ *
+ * Utility for creating a [kotlin] and corresponding [bytecode] stub, to try and make it easier to
+ * configure everything correctly.
+ *
+ * @param filename name of the Kotlin source file, with extension - e.g. "Test.kt". These should be
+ *   unique across a test.
+ * @param filepath directory structure matching the package name of the Kotlin source file. E.g. if
+ *   the source has `package foo.bar`, this should be `foo/bar`. If this does _not_ match, lint will
+ *   not be able to match the generated classes with the source file, and so won't print them to
+ *   console.
+ * @param source Kotlin source for the bytecode
+ * @param bytecode generated bytecode that will be used in tests. Leave empty to generate the
+ *   bytecode for [source].
+ * @return a pair of kotlin test file, to bytecode test file
+ */
+fun kotlinAndBytecodeStub(
+    filename: String,
+    filepath: String,
+    checksum: Long,
+    @Language("kotlin") source: String,
+    vararg bytecode: String
+): KotlinAndBytecodeStub {
+    val filenameWithoutExtension = filename.substringBefore(".").lowercase(Locale.ROOT)
+    val kotlin = kotlin(source).to("$filepath/$filename")
+    val bytecodeStub =
+        TestFiles.bytecode("libs/$filenameWithoutExtension.jar", kotlin, checksum, *bytecode)
+    return KotlinAndBytecodeStub(kotlin, bytecodeStub)
+}
+
+class KotlinAndBytecodeStub(val kotlin: TestFile, val bytecode: TestFile)
+
+/**
+ * Copied from compose.lint.test.stubs
+ *
+ * Utility for creating a [bytecode] stub, to try and make it easier to configure everything
+ * correctly.
+ *
+ * @param filename name of the Kotlin source file, with extension - e.g. "Test.kt". These should be
+ *   unique across a test.
+ * @param filepath directory structure matching the package name of the Kotlin source file. E.g. if
+ *   the source has `package foo.bar`, this should be `foo/bar`. If this does _not_ match, lint will
+ *   not be able to match the generated classes with the source file, and so won't print them to
+ *   console.
+ * @param source Kotlin source for the bytecode
+ * @param bytecode generated bytecode that will be used in tests. Leave empty to generate the
+ *   bytecode for [source].
+ */
+fun bytecodeStub(
+    filename: String,
+    filepath: String,
+    checksum: Long,
+    @Language("kotlin") source: String,
+    vararg bytecode: String
+): TestFile = kotlinAndBytecodeStub(filename, filepath, checksum, source, *bytecode).bytecode
diff --git a/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/Stub.kt b/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/Stub.kt
index 4b568a9..89df0cd 100644
--- a/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/Stub.kt
+++ b/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/Stub.kt
@@ -16,8 +16,244 @@
 
 package androidx.navigation.runtime.lint
 
-val TEST_CLASS =
-    """
+import androidx.navigation.lint.common.bytecodeStub
+import androidx.navigation.lint.common.kotlinAndBytecodeStub
+
+internal val NAV_CONTROLLER =
+    bytecodeStub(
+        "NavController.kt",
+        "androidx/navigation",
+        0x40e8c1a8,
+        """
+package androidx.navigation
+
+import kotlin.reflect.KClass
+
+open class NavController {
+
+    fun navigate(resId: Int) {}
+
+    fun navigate(route: String) {}
+
+    fun <T : Any> navigate(route: T) {}
+}
+
+inline fun NavController.createGraph(
+    startDestination: Any,
+    route: KClass<*>? = null,
+): NavGraph { return NavGraph() }
+""",
+        """
+META-INF/main.kotlin_module:
+H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuQSTsxLKcrPTKnQy0ssy0xPLMnM
+zxPi90ssc87PKynKz8lJLfIuEeIECnjkF5d4l3CJcnEn5+fqpVYk5hbkpAqx
+haSChJUYtBgAOMX57WIAAAA=
+""",
+        """
+androidx/navigation/NavController.class:
+H4sIAAAAAAAA/41SW28SQRT+ZoFl2dIW0NYWW7UXLW21Sxt9kaaJNjFug2gs
+4aVPA2zowDKb7A6kj/wW/4FPGh9M46M/ynhmIb1qdJM99++bc2bOz1/fvgN4
+jj2GFS7bYSDaZ47kQ9HhSgTSqfHhYSBVGPi+F6bBGHJdPuSOz2XHed/sei2V
+RoLB3BdSqAOGRGmzkUUKpo0k0gxJdSoihrXqP9krDNYk5xGu5G42GFKhF7lt
+BuYyzJWql2cfq1DITkXXrFWDsON0PdUMuZCRw6UMVHxA5NQCVRv4fkUzBQPl
+WcgzPOgFyhfS6Q77jpDKCyX3HVdqxki0ojTu0GGtU6/Vm8A/8JD3PSpk2Lja
+xPgCKn9qK4s5zNu4i3sMhdsFN6aZEOlplvbrL29nDkr1epwu3M4x5KuTid55
+ire54hQz+sMEPS3TIqMF6BZ7FD8T2iuT1d5lCM9HS7axYNhG7nxkG5Y26LeS
+pC36Z6z5hfPRnlFmr1M/PpmUPFrOJYpGOblqWeejXGqLUntmziwab8cF6aOZ
+cQFFLdKZKz5VlW19Mu2b7qdO+3RtCXZ6it7+MGjTCsxWhfRqg37TC+u86Xt6
++KDF/QYPhfYnwfWPA6lE33PlUESCQhev9epyERgyx6IjuRqEBLGPg0HY8t4I
+jV+c4Btj9BUQVmDQFusvSd3SUpPcJs/RvZNObX2B9ZkMA09JmnHQxDOS2XEB
+MrBJ5zEVRzT4RVxP498EWjFwfpycALU1jRmSmmKWcpqiQlpXpbcLha9YuE5k
+EvCSKH1BlCaKRcrvaFv3n5s0VkTif1izf2VdorwTV9+/zm6gHMst7JKuUnSZ
+ruTBCRIuHrp45NINr5KJNRfreHwCFuEJNk4wFcGOUIpgRtomYzNCPkIxwnTs
+ln4DameR7LoEAAA=
+""",
+        """
+androidx/navigation/NavControllerKt.class:
+H4sIAAAAAAAA/61TbU8TQRB+9o62RxUoRSqv9YWqgC9XKr6WEA0GvVjQiCEx
+JJqlXcrS6x252zYmJuon/4P/wm8aTQzxoz/KOHseCCLiBz7s7Mzs7DPPzM5+
+//H5K4BpzDCMca8W+LL20vZ4W9a5kr5nL/L2nO+pwHddETxUKTCGzAZvc9vl
+Xt1+tLohquQ1GY5VA8GVuB/wzXUGd7xyKFy58idQudLwlSs9OxBrLtn2wzmX
+h2F54iCwKFuZwT/KdDOTs4dnHKv4Qd3eEGo14NILbe55voqiQnvRV4st16Wo
+wr+iKISvuoLCkjNqXYazFtIM+ZjTRrtpS0+JwOOu7VARdF9WwxSOM/RX10W1
+Ead5zAPeFBTIcGH8LzX+9ixpkHp5Yvk4utGTRhcy9Jqh4oG6J0IlvYiZhSzD
+yL/KT+GE5iw9qWYZzHENmMPJNPoxQIAFWVgr7JkG5jD0FnSNe/1j//FqDNn9
+RTEkAr+lBMPJA0aGoW9XqkJNrPGWqxjeHOlgOvsjD52ckX2NeNEqTe8Q7N1O
+tSAUr3HF6YrRbJv0TZkWnVqAetrQikGHL6XWiqTVphjmt97m0ltv08aAES2t
+Zkj8cg2dI33IKLJJo2iUkhmT9I5St2VkEkNW1rDMAVZMPvj2ztJoJZrGw6oh
+Jpk9zbvSoCI65vwaPU5PRXpisdVcFcFTPer6Lf0qd5d5ILUdOzuXZJ1mrxWQ
+Pvyk5SnZFI7XlqGk47u/vwz9pz9Pd4Z/T1jXkuLVxgLfjBOkl/xWUBXzUhuD
+McbyPnxMwUCHbi/tg0ggSdZVsp7H/txk9tgn9F7M9pE0Z7+g/9lHDH6I4qdJ
+Jqkb3cjiGumTdKMbFoYwDP0+OYxgNMLOUUSeIrV2Cqfp7vUIIYUbMYZF+01a
+fWZsbMtOINOJMzhLuib2iq4laM+PJl6/R4ItHEjQxK1IMitimo3q6aFsvQTd
+E3HaZp3bxTqPsZh1fod1PmZt4HbEu4Qy7XforEBkzq3AdHDewQUH45hwCPKi
+g0u4vAIW4grsFaRCJEIUQ4yGyFLXQ5wKcfonI/JCLIwGAAA=
+"""
+    )
+
+internal val NAV_DESTINATION =
+    bytecodeStub(
+        "NavDestination.kt",
+        "androidx/navigation",
+        0x89e4229a,
+        """
+package androidx.navigation
+
+open class NavDestination
+""",
+        """
+META-INF/main.kotlin_module:
+H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuQSTsxLKcrPTKnQy0ssy0xPLMnM
+zxPi90ssc87PKynKz8lJLfIuEeIECnjkF5d4l3CJcnEn5+fqpVYk5hbkpAqx
+haSChJUYtBgAOMX57WIAAAA=
+""",
+        """
+androidx/navigation/NavDestination.class:
+H4sIAAAAAAAA/4VRO08CQRD+ZoEDTpSHiuAjUWOhFh4SO42Jj5iQICZqaKwW
+7oLLYy/hFkLJb/EfWJlYGGLpjzLOnTRWNl++x+zMZPbr+/0DwAm2CLtSu0Nf
+uRNHy7HqSKN87TTk+NoLjNKRTIIIua4cS6cvdce5a3W9tkkiRrDOlFbmnBDb
+P2hmkIBlI44kIW6eVUDYq//f/pSQr/d801faufWMdKWR7InBOMZLUgjpEECg
+HvsTFaoKM/eYsD2b2rYoCVvkmM2mqWJpNq2KCl0mPl8skRNhXZXC1/m/c496
+hve88l2PkK0r7TVGg5Y3fJStPjuFut+W/aYcqlDPTfvBHw3b3o0KRfl+pI0a
+eE0VKE4vtPZN1DjADgSfYb5zeBXGEisn0kDi8A2pVyYCZUYrMuNYZ8z8FiAN
+O8o3IlzDZvRhhAXOMk+I1bBYw1INWeSYIl9DActPoAArWOU8gB2gGMD6AQ9d
+W4PtAQAA
+"""
+    )
+
+internal val NAV_GRAPH =
+    bytecodeStub(
+        "NavGraph.kt",
+        "androidx/navigation",
+        0x54a108f5,
+        """
+package androidx.navigation
+
+open class NavGraph: NavDestination() {
+    fun <T : Any> setStartDestination(startDestRoute: T) {}
+}
+""",
+        """
+META-INF/main.kotlin_module:
+H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuQSTsxLKcrPTKnQy0ssy0xPLMnM
+zxPi90ssc87PKynKz8lJLfIuEeIECnjkF5d4l3CJcnEn5+fqpVYk5hbkpAqx
+haSChJUYtBgAOMX57WIAAAA=
+""",
+        """
+androidx/navigation/NavGraph.class:
+H4sIAAAAAAAA/31SXU8TQRQ9s2232wVpAUGo4AegFFC2Ep8sIfEjaE2tSpu+
+8DRtN2X6MWt2pg2P/S3+A580PpjGR3+U8c62aA3iJnPvnXPvuXNm7/z4+fUb
+gMfYZ1jjshkGonnuST4QLa5FIL0yH7wM+YezJBjDxhUVL3ylhYy2ScQY7EMh
+hT5iiOV2arNIwHYRR5Ihrs+EYrhV+t9RBYZF5euK5qGe6sywlCu1+YB7XS5b
+3tt622/owk6NhB9Wn1zOHOWq1Si9WQrCltf2dT3kQiqPSxnoqKXyyoEu97td
+OnJOXZx3EvS17yBNOjuB7grptQc9T0jth5J3vaLUIbURDZXEPIlqnPmNzqTP
+Ox7ynk+FDNv/EDuFVEyTVsH8nkVcd7GAJYaFyxSG+dJExRtf8ybXnDCrN4jR
+2JgxKWPAwDqEnwuzy1PUfMTwfjTMutaKNV4OrYzljobkjHEsZ3llNDyw8uxZ
+4vtHm5Kv1zOxrJWPbzjOaJhJ7Fp5+8DOJLPWq3GBYxofMGxdNcCpeZFMo6rK
+MHMx2f2OpjfwPGj6DOmSkH6536v7YZXXu765fdDg3RoPhdlPwFRFtKhfP6R4
+66Qvtej5RTkQSlD69+9++mekDG4l6IcN/1gY/uqEUxszpgpxFxa9SvNZJJQe
+Kdlt2nlGNvnE7mc4n6J0jqwdgXHskJ0dFyAFl/w8ZgiJReQCVVvkk3sLmS9Y
+/ptuE8XQl8clE7qJ0rhB+d2o+hr2DGZEzEXAg8jex0Pyx4SuUJvVU8SKyBZx
+s4g1rFOIW0Xcxp1TMHO1jVOkFFyFTQVbYUZhS+FeZNMKs78AJaVXJ/gDAAA=
+"""
+    )
+
+internal val NAV_HOST =
+    bytecodeStub(
+        "NavHost.kt",
+        "androidx/navigation",
+        0x5ce5aeda,
+        """
+package androidx.navigation
+
+import kotlin.reflect.KClass
+
+interface NavHost
+
+inline fun NavHost.createGraph(
+    startDestination: Any,
+    route: KClass<*>? = null,
+): NavGraph { return NavGraph() }
+""",
+        """
+META-INF/main.kotlin_module:
+H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuQSTsxLKcrPTKnQy0ssy0xPLMnM
+zxPi90ssc87PKynKz8lJLfIuEeIECnjkF5d4l3CJcnEn5+fqpVYk5hbkpAqx
+haSChJUYtBgAOMX57WIAAAA=
+""",
+        """
+androidx/navigation/NavHost.class:
+H4sIAAAAAAAA/32OzUoDMRSFz81of8a/qVqoiK9g2uLOlZviQFVQcDOrtBNL
+OtMEmnToss/lQrr2oaR3qmsTOPecc+FLvn8+vwDcoUu4VjZfOpOvpVWVmalg
+nJXPqnp0PjRBhGSuKiVLZWfyZTLXU24jQmdcuFAaK590ULkK6p4gFlXEWKql
+XQsIVHC/NnXqs8sHhO5204pFT8QiYffR226Gok/1cki4Gf/zH36DkfFfui0C
+hze3Wk71yJSacPW6ssEs9LvxZlLqB2td2AN8g/E4wO8RuNjrOS55Dhh5yLeR
+IUrRTNFK0UbMFkcpjnGSgTxOcZZBeCQenR1YLcIOPwEAAA==
+""",
+        """
+androidx/navigation/NavHostKt.class:
+H4sIAAAAAAAA/61TbU8TQRB+9o62R1EsRSogrW9VAV+uVnwtIRqNerGgEUNi
+SDRLu5Sl1ztzu200JsZP/gf/hd80mhjjR3+UcfY8QUTgix92dmZ25plndme/
+//j0BcAMZhmKPGhGoWy+cAPeky2uZRi4C7x3L1T6vs6AMeTWeY+7Pg9a7oOV
+ddEgr80w0IgE1+JuxJ+vMaxO1ncBqtX/hqjV26H2ZeBGYtUn271/y+dK1aZ2
+gonr1Bjk/yk0Oz23d60T9TBquetCr0RcBsrlQRDqOEq5C6Fe6Po+RZV3i6IQ
+vuILCkvP6jWp5hxkGUoJp/Vex5WBFlHAfdcLdET5sqEy2Mcw0lgTjXZS5iGP
+eEdQIMPpyX/0uOlZNCCt2tTSPgziQBb7kaMXVJpH+rZQWgYxMwd5hond2s/g
+oOEsA6nnGOxJA1jAoSxGMEqAZVleLW+ZAOYxDJVNj1v9xV3fiyG/vR2GVBR2
+tWA4tMOYMAz/UaTcFKu862uGl/9pDL3tkXtOy8S25p91qzMb1IZ+l5oXmje5
+5pRidXo2fURmRL8RoHtsG8WiwxfSaBXSmhcY7nx9U8h+fZO1Rq14GTVH4pdr
+/CTp41aFTVsVq5rO2aT3VQcdK5cad/KWY4+ySvret7eOQavSBO7VDTHJJtd2
+vk30+26FTXqQA3UZiIVuZ0VEj81gm/cLG9xf4pE0duLsX5QtmrRuRPrhR91A
+y47wgp5Uko5vbn4Q+j1/n26M+paw/YuaN9rz/HlSILsYdqOGuCONMZZgLG3D
+xwVY6DMXS/sYUkiTdZGsp4m/MJ0f+IihM/lhkvbcZ4w8+YCx93H8DMk03cMg
+BnCJ9GnKGISDcRyGeZkCJlCMsQvIo0SRRjuCo5R7OUbI4EqC4dB+ldawnRi/
+ZT+Q68cxHCfdEHtFaSnaS8XU63dIsfkdCdq4FkvmxEzzcT8OVcuSdIjJJuvC
+H6xLOJGwLm2wLiWsLVyPeVdRo/0GnZWJzMll2B5OeTjtYRJTHkGe8XAW55bB
+FM7DXUZGIaVQUSgq5OnWFY4oHP0JmQ7w4mgGAAA=
+"""
+    )
+
+internal val TEST_NAV_HOST =
+    bytecodeStub(
+        "TestNavHost.kt",
+        "androidx/navigation",
+        0x2f602e26,
+        """
+package androidx.navigation
+
+class TestNavHost: NavHost
+""",
+        """
+META-INF/main.kotlin_module:
+H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuQSTsxLKcrPTKnQy0ssy0xPLMnM
+zxPi90ssc87PKynKz8lJLfIuEeIECnjkF5d4l3CJcnEn5+fqpVYk5hbkpAqx
+haSChJUYtBgAOMX57WIAAAA=
+""",
+        """
+androidx/navigation/TestNavHost.class:
+H4sIAAAAAAAA/4VRTUtCQRQ99z01fVmpfWlW0q5a9EzaFUEFkWAGJW5cjb5H
+Teo8cEZp6W/pH7QKWoS07EdF9z2jWgQt5nDOuXe4Z+68f7y8AjhAiVASyhsE
+0ntwlRjJW2FkoNyGr01djC4CbWZAhMy9GAm3J9Ste9W+9zvs2oTiX1e/r8UJ
+iSOppDkm2Ns7zTRmkHQQQ4oQM3dSE7Zq/ww/JGRr3cD0pHIvfSM8YQR7Vn9k
+c34KIRUCCNRl/0GGqszM2ydsTMaOY+Wt6EzG+cm4YpXpNP72mLAyVthU4aY/
+M/zMn/8VZ69rOPtZ4PmEhZpUfn3Yb/uDhmj32MnVgo7oNcVAhvrLdG6C4aDj
+n8tQFK6Hysi+35RacvVEqcBE8zT2YfFqeGXTx4S7Ylxj5UYaiO8+w3liYqHI
+mIjMGNYZ09MGzDIL6xsRFrAZfTJhjmvzLdhVLFSRqSKLHFMsVrGE5RZIYwWr
+XNdIa+Q1kp+Mv2/DIQIAAA==
+"""
+    )
+
+internal val NAVIGATION_STUBS =
+    arrayOf(NAV_CONTROLLER, NAV_DESTINATION, NAV_GRAPH, NAV_HOST, TEST_NAV_HOST)
+
+internal val TEST_CODE =
+    kotlinAndBytecodeStub(
+            "Test.kt",
+            "androidx/test",
+            0xef517b0b,
+            """
+package androidx.test
+
 val classInstanceRef = TestClass()
 
 val classInstanceWithArgRef = TestClassWithArg(15)
@@ -66,4 +302,477 @@
 abstract class TestAbstractComp { companion object }
 class AbstractChildClassComp(val arg: Boolean): TestAbstractComp() { companion object }
 object AbstractChildObjectComp: TestAbstractComp()
+""",
+            """
+META-INF/main.kotlin_module:
+H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuQSTsxLKcrPTKnQy0ssy0xPLMnM
+zxPi90ssc87PKynKz8lJLfIuEeIECnjkF5d4l3CJc/HCtZSkFpcIsYWkgiSU
+GLQYABRWGrdkAAAA
+""",
+            """
+androidx/test/AbstractChildClass.class:
+H4sIAAAAAAAA/4VQTWsTURQ9781XMk3MJH6labW1KrRZmLS4U4ppQAhMu6gl
+i2T1khnaRyYzMO9Fusxvce1GUAQXElz6o8T7JlUQFBfv3HvuO5z78f3Hl68A
+nuMpw65IozyT0XVHx0p3ehOlczHV/SuZRP1EKOWBMbT+VF0Q/FJ6sBjclzKV
++pjB3h8dDBms/YNhBQ48HzZKxEV+ycBGFfjYKIOjQlJ9JRXDXvi/CV6Q/2Ws
+e8aCjEcM9XCW6USmndNYi0hoQRI+f2vRUsxA2QCo4Yzq19KwLmXRIcPJatnw
+eZMXb7X0ebDh85LVXC2PeJedVBtuwFu8a3175/LAPq//ZiVSt+ySE7jG6Yhh
+O/z3UWgeau+Z0rOZpl37WRQz1EKZxmeL+STOL8QkoUojzKYiGYpcGn5T9N9k
+i3wav5aGbJ4vUi3n8VAqSb+9NM200DJLFQ7pkHaxaMPclTJOuQOXcJfYMXFO
+0W9/Rrm99QnVD4XmEaHRADvYI7y3VuEWauZulBk3OjMCemuvjjknRaf9EdX3
+f7WprAU3NhyPC9zBE4qviiEd3B7DGuDOAHcH1PY+pWgOsInWGExhC9tjeAo1
+hQcKvsJDBVchUKj/BOsI9uW0AgAA
+""",
+            """
+androidx/test/AbstractChildClassComp$Companion.class:
+H4sIAAAAAAAA/5VSTW/TQBB9u07jxARIWz4SvgolSC0SdRJxK0IqQUiRUpCg
+yqUHtLG3dBN7jbybqMec+CH8g56QOKCoR34UYtYJcKWX2Zn35s143/rnr+8/
+ADzHE4Y9oeM8U/FZaKWx4cHI2FxEtneqkriXCGN6Wfq55YLQKtM+GEN9LGYi
+TIT+FL4bjWVkfXgM5RdKK/uSwdvZHdawhnKAEnyGkj1VhqE9uNyqfYbOzmCS
+2UTpcDxLQ6WtzLVIwtfyREwT28s0TZhGNssPRT6R+f7uMAB3Kzdb0T/yY1qw
+dNfLTWNY/yM4lFbEwgrCeDrzyDzmQtUFMLAJ4WfKVW3K4g5DazEPAt7gAa9T
+tphXLr54jcW8y9vslV/hF1/LvM5db5e5Ca3/8cbHXYbqX4MY/CNq3ptY8riX
+xZLh+kBp+XaajmR+JEYJIRuDLBLJUOTK1Suw1tda5sVcSS8TfMimeSTfKMc1
+30+1VakcKqOo+UDrzApL6ww6ZG7J3ZhO7h6YPnyLqtBZQOfa02+onBf0Q4rl
+AuziEcXasgFVBECdUXZlJX5GJ1+Ja+eFnU5wawkuBUV2FdeI87BNVVCI7uE+
+mnhcLHyAVvFLkwfUWz+G18d6Hxt9bOIGpbjZp5m3j8EMGmgSbxAY3DEo/wZN
+V6SgDwMAAA==
+""",
+            """
+androidx/test/AbstractChildClassComp.class:
+H4sIAAAAAAAA/41SW08TQRT+ZrfXZZFSEQt4QUEsVdlCfBJCgjWaJoUHJE2E
+p2k7wtDtrNmZEh75LT77QtSQaGKIj/4o45lthRiN4WHPmXP2O9+5/vj55RuA
+p1hhmOeqE0eycxwYoU2w0dIm5m1TO5BhpxZyrWtR710WjOHOn8gdEhfoBOMy
+ZNakkmadIVXeXWwyuOXFpo80sh5SyJHN430GtuvDw0geDnyCmgOpGRYaV6lk
+lXLsC7NhaYh8lyG31g6HSZeuwjBvBVcyUllcZ1guN7qRIYbg8KgXSGVErHgY
+vBBveT+kxhRx9Nsmijd53BXx6qCfGx4mMMmQvyBjqF6pgcv0qz5KmLJDmGaY
+a0TxfnAoTCvmUumAKxUZbgimg63IbPXDkFof/13rpjC8ww0nn9M7cmmZzIq8
+FaABd8l/LK1VpVdnmeHV+UnRc0pO8p2feE5hxHNyqdL5yWx2xamyZyz7fLSY
+KTjTTtX9/j7jFFLb4xdWjkKmU7l0IWPp6GxmG/+/BiqM6sha91LXMMxs95WR
+PVFXR1LLVig2LhukE6hFHcEw1pBKbPV7LRHvcMIwFBtRm4dNHktrD51+XSkR
+JxMVFOy9jvpxW7yU9t/UME/zryxYpkmnaCIOpuzgqbxHZGVI3yJdtBdJ2iU7
+nXgfk7VOaIe0VzlDvjLzGaOnCcOTYSSwgiWSkwMUrmHMboBelo0WhgJ9A67A
+LoZ0uvIJox/+SeMPAEOaHBWVHQaXkKwW/ldMvGFnuPkRM6eJxyVim5DRRTpJ
+Y9WEu0INAzXy3ybGO3tw67hbx2wd93CfnpirYx4P9sA0FvBwDzmNMY2yhqex
+qJHRKGiMa5R+ATUXZWovBAAA
+""",
+            """
+androidx/test/AbstractChildObject.class:
+H4sIAAAAAAAA/4VSXWvUQBQ9M7ubZNPV1vrR3bZ+1PqgPpi2+GYR1kUhECPY
+ZaH0aZIMdrrZDCSzpY/75A/xHxQfCgqy6Js/SrwTV0VETMi995w5c27mJl+/
+ffgE4DHuMWyJIiu1ys4CIysT9JPKlCI1g2OVZ6+SE5kaF4xh/U/ZkMJPqYsG
+g7OvCmWeMjTuPxh10ILjowmXoWmOVcWwHf23zxMGbz/Nax8f3G72wvhg2I8H
+zzu4BL9N5GVrpcs3wYk0SSlUUQWiKLQRRmmqY23iaZ6T1ZVorA2ZBS+lEZkw
+gjg+OW3QuZkNbRvAwMbEnymLdqjKdqnBfOb7vMvrZz7zvrzl3flsj++wZ67H
+P79z+Aq30j2Gzejfc6GGrsWPxoZh4/W0MGoiw+JUVSrJZf/3W9OQBjqTDMuR
+KmQ8nSSyHArSMKxGOhX5SJTK4gXpH+hpmcoXyoLewnj0ly12aV7N+pA9Oz7K
+twg5lFcoc7pbNbpNKLCjoNx6eAHvvF6+sxCDqi2KnR8CtMkK8LD0a/Maqe21
+9BH88AKd91g+rwmOu3W8ie36f6PPQgarR2iEuBriWojruEEl1kJ00TsCq7CO
+DVqv4FfYrOB8Bw71GM6sAgAA
+""",
+            """
+androidx/test/AbstractChildObjectComp.class:
+H4sIAAAAAAAA/41SXWvUQBQ9M7ubzaarrfWju1Zrv6TVB9NW3yzCuigEYgS7
+LEifJpuhnW42I8ls6eM++UP8B8WHgoIs+uaPEu/EpSKCmJB77zlzciY5yfcf
+n74AeIJNhvsiS3KtkjPfyML4nbgwuRiY7rFKk9fxiaRRj97VwRhW/pT2qFzK
+S02FwdlXmTLPGCrbD/pN1OB4qKLOUDXHqmDYCv9rv6cM7v4gLb08cGvgBtFB
+rxN1XzRxBV6DyKsMG6HOj/wTaeJcqKzwRZZpI4zSNEfaROM0Jatr4VAbMvNf
+SSMSYQRxfHRaoQyYLQ1bwMCGxJ8pi3ZoSnZpg+nE83iLl9d04n57z1vTyR7f
+Yc/rLv/6weEL3Er3GFbDf+dDm9Yt92hoGJbfjDOjRjLITlWh4lR2fj85hdXV
+iWSYD1Umo/EolnlPkIZhMdQDkfZFriyekd6BHucD+VJZ0J4Z9/+yxS5lVi1f
+tG0jpL5CyKG+QJ3TWSvRPUK+jYN67eEF3PNyeXUmBh5jjWrzlwANsgJczF3e
+vERqe8x9Bn97geZHzJ+XBMd6We9io/z/6NOQweIhKgGuB7gR4CZu0YilAC20
+D8EK3MYyrRfwCtwp4PwEJ9evBbwCAAA=
+""",
+            """
+androidx/test/InterfaceChildClass.class:
+H4sIAAAAAAAA/4VQz28SQRT+ZhZY2FJZqFYKVq21teXg0sabprElMSFBTWrD
+AU4DO9Ipy26yMzQ98rd49mKiMfFgiEf/KOMbSpqYGD3M9973fnxv3vv569t3
+AM/whGFLxGGaqPAqMFKboB0bmb4XQ9k6V1HYioTWLhiDfyEuRRCJeBS8HVzI
+oXHhMNT/bD4juBFwkWXIvVCxMkcMmb3efpfB2dvvFuGi4CEDj7hIRwysV0QR
+qwVw3KJSc640w3bnvz97TgNG0hxbDVLuMZQ748REKg5eSyNCYQSV8MmlQ9sy
+CwULoIljil8py5rkhQcMJ/NZxeNVvnjzmcf9FY/nnep8dsib7GS1kvN5jTed
+Hx9y3M+clm9YnqprmXzWz1mlQ4bNzj/OQh+i+a6NPR0b2raVhJKh1FGxfDOd
+DGR6JgYRRSqdZCiirkiV5cug9y6ZpkP5SlmycTqNjZrIrtKKssdxnBhhVBJr
+HNApMzQnR69ib0uLcjsXecJHxI6Ic7Je4ytWGvUvKH1a1GwT2i6gjseE69dV
+8FG2pyPPqtGlSXdtqRXYi5LNNj6j9PGvMsXrgqUMx84Ct7BL9iXlblPuTh9O
+G+tt3G2jig1yUWtT/70+mMYm7vfhapQ1HmgUNR5q5DUqGmu/ARpxRv/QAgAA
+""",
+            """
+androidx/test/InterfaceChildClassComp$Companion.class:
+H4sIAAAAAAAA/5VSTW/TQBB9u07jxARIWz4SvqGp1CJRNxW3IiQIQrKUggRV
+Lj2gjb1tN7HXyLuJesyJH8I/6AmJA4p65EchZp0AV3qZnXlv3sz6rX/++v4D
+wHNsMoRCJ0WukrPQSmPDSFtZHItY9k5VmvRSYUwvzz53XBBa5doHY2iOxFSE
+qdAn4fvhSMbWh8dQfaG0si8ZvK3tQQMrqAaowGeo2FNlGLr9S+7aJ81Wf5zb
+VOlwNM1C5RRapOEbeSwmqe3l2thiEtu8OBDFWBb724MA3O1c78T/yE9ZyTLs
+XG4aw+ofwYG0IhFWEMazqUf2MRfqLoCBjQk/U67apSzpMnTmsyDgLR7wJmXz
+We3ii9eaz/b4Lnvt1/jF1ypvcte7x9yEzf8yx8ddhvpfhxj8Q+reGVtyuZcn
+kuF6X2n5bpINZXEohikha/08FulAFMrVS7ARaS2Lcq6ktwk+5pMilm+V49of
+JtqqTA6UUdT8SuvcCkvrDLrkbsV9Mp3cPTHd/CFVofOAzpWn31A7L+lHFKsl
+GOIxxcaiAXUEQJNRdmUpfkYnX4ob56WfTnBrAS4EZXYV14jz8ISqoBTdw320
+sVEufIBO+VeTB9TbPIIXYTXCWoR13KAUNyOaefsIzKCFNvEGgcEdg+pvYvaF
+YBIDAAA=
+""",
+            """
+androidx/test/InterfaceChildClassComp.class:
+H4sIAAAAAAAA/41S308TQRD+9lp67XFIWxRLEUUBKVW5gjwJIcEaTZOCCZIm
+wtO2Xcq11z1zu2145G/x2ReihkQTQ3z0jzLOlgoxGsPDzTczN/PNr/3x88s3
+AGtYY1jgshmFfvPY00JpryK1iA55Q5SP/KBZDrhS5bD7zgZjSLd5n3sBly3v
+db0tGtpGjGH6T4I9EpckNkYYEhu+9PUmQ7ywv1RjiBWWai5spBzE4ZDNoxYD
+23fhYiwFCzcoVB/5imGxeq3u1qlIS+gtw0Ps+wzJjUYwrOpdi2LeCC79UNq4
+xbBSqHZCTRReu9/1fJMjeeC9EIe8F+hyKJWOeg0dRts86oho/WKi2w4mkWNI
+XZIR0/VGuKq/7iKPabOHOwxz1TBqeW2h6xH3paJZZKi5pjDl7YR6pxcENHzm
+d7PbQvMm15x8VrcfoxszI1JGgHbcIf+xb6wSac0VhlfnJ1nHylmD7/zEsdKj
+jpWM585PZu1Vq8SeMfv5WDaRtvJWKfb9fcJKx3czl1aSUvLx5Eg6YehWGWaq
+/3kN1BU1YRvfckfTy9ntSe13RUX2feXXA7F1NR09gXLYFAzjVV+KnV63LqI9
+TjEM2WrY4EGNR76xh063IqWIBusUlOy8CXtRQ7z0zb+pYZ3aX1WwQmuOU1MJ
+wimzd9Kf0HoShHcJs+ZNEsZM40iSXCZrk6ItQqd4htHi9GeMn5JlwRtmgrQS
+ycmLKKSRMQcgzbDRvYh3YsjlmbsQjhQ/YfzDP2nci4AhTRI3kRom5zC4LNyv
+mHzLzjD1ETOnA0+MRjMF2aCJPA23OuB+jKeEZfLfI8bZA8QquF/BgwrmME8q
+Fip4iMUDMIUClg6QVMgoFBVchUfKmFmFCYX8L78zjKNFBAAA
+""",
+            """
+androidx/test/InterfaceChildObject.class:
+H4sIAAAAAAAA/4VSy27TQBQ9M0ljxzU0La+EUh59IGCB24odFVKJQLJkgkSj
+SKiriT1tJ3HGkj2JusyKD+EPKhaVQEIR7PgoxB0TihAS2Jr7OHPvuZ4z/vb9
+42cAT3CfYV3oJM9UchoYWZgg1EbmRyKW7ROVJq/7AxkbB4yhMRATEaRCHwe/
+0ArD6p/dXTIXDA4WGGp7SivzjKHy4GHPhwPXQxV1hqo5UQXDZvT/+U8Z3L04
+LYk8cNvthp2D7n6n/cLHEvw6gQ2GjSjLj4OBNP1cKF0EQuvMCKMyijuZ6YzT
+lKiWo2FmiCx4JY1IhBGE8dGkQoIwa+rWgIENCT9VNtumKNmhAbOp5/EmL9ds
+6n59x5uz6S7fZs8dl395X+MNbkt3GdaifyhDEx0LPB4akvDNWBs1kqGeqEL1
+U7n/+7NJpnaWSIalSGnZGY/6Mu8KqmFYibJYpD2RK5vPQe8gG+exfKls0poT
+9/6ixQ4JVqUz1mi1rILk79JBbb5CntNLV0XZPcoCqwb5hUfn8M7K7fV5MXAL
+G2T9nwVYpAjUeOmi+QZV22fxE/jbc1z+gOWzEuDYLO0dbJX/IsMVIrh6iEqI
+ayGuh9TapBCtEDexeghW0LA12i/gF7hdwP0BVe1yPcgCAAA=
+""",
+            """
+androidx/test/Outer$InnerClass.class:
+H4sIAAAAAAAA/4VU308cVRT+7sz+mB0WmOVXKay0yorL0nYAW62FVgFFBpel
+QkOs+HLZvcLAMoMzs6S+GJ76JzTRFxNjfOKhTRSMTQy2b/5NxnjuznS3LgSS
+mXvOPXPOd757zrnz979//AngJlYZhrhT8Vy78sgMhB+Yy7VAeDnLcYQ3V+W+
+nwRjMLb5Pjer3Nk0lze2RTlIQmVITNuOHdxjiOWt0TUGNT+6lkYcSR0xaAya
+LVFmvE0GZqWhoy0FBWnyD7Zsn+Fq8fzUUwxtmyKwGiiUwGLQy+7unusIJ5gg
+qLK79y3DMDG4GG246Hqb5rYINjxuO77JHccNeGC7pJfcoFSrVqfkARI68exj
+SEvwXEV8zWvVgGEtf1EKyyq2VmrqQl5pdKNHZhygkgXuauDZDh22Jz/6Glho
+pTNcarXN1uxqRXhJDOm4Isve08TOv+rAXQ1vUsP43p5wKgzX86ehT2eLkIng
+MHIS/G2GrCz0eY7vSMe8dJw737EgHcfSyOINqV2nw29xf2vOrQiGTDPScgKx
+Kc83Hg4aTZKJSR0TeJdOJL6p8SrNUm/+jMp/yZA7r+XUb75RFVTVuBtsCY+h
+6zQKkSnuuEHVdswlEfAKDzjZlN19lW4Qk0tKLqAh3yH7I1vuiKtSofH8+eRg
+SFf6FV0xTg50ehRD0xUtQbKNpEqyQ3vxWOs/OZhUxtlse1fCUAaUcfXFTwnF
+iC2mjKTcLbx8rC52Gxrp5KhpSuhEZkbmFOn6pGa0DcT62ThbePlEpcB06PGE
+kd5OeofUVzINeI3oDMS0uJGQXCeZPEH3GaOaxDzdueZMMSQf0McbO3QjYmG3
+Oou2I0q13Q3hPZAFlXV0y7y6xj1b7iPj4ErNCexdYTn7tm+TaabZDIb21YCX
+d5b4XuSda/W+zz2+K4jR/8LSTWaCtvqqW/PKYt6WEJcjiLVT6Wh6FPpJyTN3
+yR8TaRrpdPVpXaTdPH1XSOqFY6QKg7+h/RntFHxGawdki3spvg8pkkXa9YXe
+9K1TDgNpEpVmBwa9IaYpZ4RkvPAr2g8bcIm6sa8Okw4dIpgMkXsVPNwazM4M
+oF8JwcqACWIpOaWeQ3k4eIxLTxtBIdlUg2wqIrsUsekFjBT6cTnKPRIVK5ON
+ffc9NMlgujB4hMEQskSrCiYR6DJH6e+QlNSyz3Hl4TGudr11hBEZeYRRY/QI
+145w42nLMbIRo9d40Go2ajAS1aDO4HfcbC2DFsUz3MJ7EY+vSMp25QpjvyAe
+Oxz7C8oPiKuHYydQliTQNXp/lJZY2JNSvX1qUvsHmSTtmxXLNSqWw218QHmW
+SU9KUu/Xa3C/Hkr3CZ9igcr3eR3QwgrJL8h+hzo1tQ7VwrSFuxbu4UNS8ZGF
+Gcyug/mYw8fr6PTl84kPvb4mfBg+Mj66fHT7uFU33vZh+siS/h/DktczzQcA
+AA==
+""",
+            """
+androidx/test/Outer$InnerObject.class:
+H4sIAAAAAAAA/4VUS08TURT+7p0+ptMChSIUUBCpykNpQV1BTJRoHCzFCMEo
+q9t2hKHtjM7cEpas/AkuXLpwxULigkQTg7Dzf/g3jOdOR4vgI2nP+c655zXf
+uTNfv3/8DOAmbjGMCKfquXZ1Jy8tX+aXm9LycqbjWN5yecuqyDgYQ3pLbIt8
+XTgb+Z9ejSE2bzu2vM2gjU+spRBFzEAEcYaI3LR9htHif2rPMejSXZGe7Www
+9I5PFNt9Wl6KGCu63kZ+y5JlT9iOnxeO40ohbZdwyZWlZr1OUckTZXV0UuFN
+4W8uuFUrGM/Uto6+PaSRrZdNUafZzo0XTz/T3MQzhty/ulErUa5b1C7qyk3L
+Y+g5W4Vaz1fqATMGuKJDN0srq3dKC/dSGISRIOcQQ3ex5koKyy9ZUlSFFJTI
+G9sa7YUpkVACDKxG/h1bWQVC1RmG54e7wwbPcoOnD3cNriuQDLVuKFe6Uz9+
+ZWQPd2d5gd2N6/zobYyn+WImrQ3yQmRWT0cHI1lWYA+OX2uLiXSMvHHCjLBO
+OKGw6jbL1AyZP+wxjgmG+CrZ0zXJMPS46Ui7YZnOtu3bRNKdNnF0IVqL6Cra
+jlVqNsqWt6qIVPy5FVFfE56t7NDZsSJFpbYkXoR27nTtR8ITDYuG+K1JKrgC
+C3Xh+xaZxorb9CrWfVuVGAhLrJ0ZDjO0j0hA9YBaD+lrZMVId5CO0mk0sK6T
+lVcLUd7JA+j7BDimw2AgQ8dAqhWABJVSRZPk4UHyaJis9XS9D47a4VoYfrIz
+vXXoDvu2U3v2/pJKW0Jv2MkkzUn3T069QzSyN/UF/A2i2t7UIfiTyF4weIFk
+BDyuB8X6WglhMYX66M+IHagrTC8MAR3ZX1T0BwlA8hP40wMMfMD5/cChYZak
+4pFjEp3E6o2g3xR9b9RoDBeInuF1aCZGTFw06ekuEcSYiRwur4P5uIKr6zB8
+9Rv3EfORCUCfj3QAkiR/AL5kiZ3FBAAA
+""",
+            """
+androidx/test/Outer.class:
+H4sIAAAAAAAA/3VRwW7TQBB9u05ixzE0TSlNKE2BFmiKhNuKU6mQSgSSpZBK
+bRQJ5bRJVmUTx5bsTdRjTnwIf1BxqAQSiuDGRyHGbiAHileetzPz5s3u7M9f
+X74BeIFnDCsi6Eeh6l+4WsbaPRlrGZlgDMWBmAjXF8G5e9IdyJ42YTDkjlSg
+9CsGY6fWdpBFzkYGJkNGf1Axw2rjBr2XDNZRz08rbfCEbnnNs9Zxs/7GwS3Y
+eQreZthqhNG5O5C6GwkVxK4IglALrULaN0PdHPs+SS03hqEmMfed1KIvtKAY
+H00MuhFLTD4xYGBDil+oxNujXX+foTabOjYvc5sXZ1ObW4b14yMvz6YHfI8d
+ciPz2rT49085XuRJwQFLZGwvCGRU90VM1yukzvU8GKo33HV7QTexybD5X86f
+qT5kMFuUez4kyfXTcaDVSHrBRMWq68vjxQxoyPWwLxmWGiqQzfGoK6OWIA5D
+qRH2hN8WkUr8edBZHEVSsX0WjqOefKuSXGXep/1PF+zTY2TSCVaStyHcJi9H
+WCTktLKp95g8N5kzYXb3CtZlmn4yJwMlPCXrXBOQJynAQuFv8Rqxk6/wFfz9
+FZzPWLpMAwZ20nKOB/Rv0DkeEVYJa2mLLewSHpLMMgmXOjA8rHi442EVd2mL
+NQ9lVDpgMe5hvYNsDDvG/Ri5GBsxqr8BxLf8XAEDAAA=
+""",
+            """
+androidx/test/OuterComp$InnerClassComp$Companion.class:
+H4sIAAAAAAAA/5VTTW8SURQ9d4YyMGKlVC34/YGVGu0AcVdjohgTEmqT2rDp
+wjzgqQ+GN2bmTdMlK3+I/6ArExeGdOmPMt43oI0LE7u599x77rk3cx78+Pnt
+O4CnaBCaQo/iSI2OAyMTE+ylRsadaPqp3tWaUSiSJCttEFpF2gMRymNxJIJQ
+6A/B3mAsh8aDS8g/U1qZ5wS3sdUvYQV5Hzl4hJz5qBJCu3feYzuEVqM3iUyo
+dDA+mgZKs0SLMHgl34s0NJ1IJyZOhyaKd0U8kfHOVt+HY4+u14dn5LtpxhK2
+z7eNsPZbsCuNGAkjuOdMj1w2kGwo2gACTbh/rGzVZDRqEerzme87Vcd3yozm
+s8LpZ7c6n7WdJr30Cs7pl7xTduxsm+yGzf9zx8N1wsY/Zj3cJKz+LSAU/xhK
+8A5YsD0x/CqdaCQJl3pKyzfpdCDjAzEIuVPpRUMR9kWsbL1sls6WSn5L/22U
+xkP5Wlmutp9qo6ayrxLFwy+0jowwfC5Bix8jZx3i7NifBH/oPa4CaxnnlUdf
+UTjJ6Psc81nzMeocS4sBFOEDZWJ0YSl+wtlZiksnmf1WcHXRXAgydBGrzLl4
+wFWF2Ru4hduoZegO583s8F08zP4O7AVryodwu1jrotLFOi4zxJUu7944BCWo
+osZ8Aj/BtQT5X3gloppLAwAA
+""",
+            """
+androidx/test/OuterComp$InnerClassComp.class:
+H4sIAAAAAAAA/41UXVMURxQ9Pfs1Oywwi18IJJq4McuuukA0MYqJijEMATRi
+iGjy0OyOMLDMkJlZyrykfPInWJW8pCoPeeJBKwmkYlWK6Ft+UyqV0zPjomAs
+qqD73ru3zz197u35+98//gRwGl8LHJduw/ecxr1aaAdh7VortP0xb2W1ZLku
+raYMAuXmIATMJbkma03pLtSuzS/Z9TCHlEB21HGd8COBdNkanBVIlQdnC8gg
+ZyANXUB3FNIlf0FAWAUY6MhDQ4H54aITCJQn90bhvEDHgh1abTQWsgSMOn/z
+XNsNhwlZ91a/FaiSyd5Rj016/kJtyQ7nfem4QU26rhfK0PFoT3vhdKvZPK8u
+lDXI+6BAQRUpNey7stUMBe7u+QKWNblTwfN75lnAPuxXDPooaejNhL7jUoT9
+5cEXQOMo73RoZ+xyy2k2bD+HNw0cUW3pfRm//LxLF3S8xabK1VXbbQicLO+G
+310xQSfJYyipAu8IDKgmvC7xXZVYVoljr0+sqMRqAQN4Q1knKcCiDBbHvIYt
+UNw+abmhvaDuOBQPI6ethhEDw3iPN7K/ackm5+1A+RVduC1Qet0YcAbkfNOm
+shkvXLR9gZ7dKOQ1Wm8mr2Fob30tqUW6rJIDAYbLk8teSIza0tpKzeGFfFc2
+a1fiYRsjl9Bv1UPPn5L+MuWJn9oFA6NgzXwbTGBkj4O1TYBaX8Ql9TgvU9bn
+PKbsUDZkKElOW1lL8bsh1JJXC/iklxm/5yiPqmsNPsL1rftHDa1XMzRz677B
+P83UDU3Pcu/gnuLexbD+9IHey9TuEW1InBPdlzt7sqbWpw2lnv6U1cz0RN7M
+KW/82YPUxD5Tp711f0TXtTiJYcFwnrYxopsdfeleMSTGnz1M8WAhzngoaHfS
+7lL2jWIbXmf9vrSeMbOK84hQNzn0P3rlcF2g62XRBHI3mXRqme+//0bLDZ0V
+23LXnMDhkFzaHhzOYTyl3ZOOa0+3VuZt/6YaJDU/Xl02Z6XvKD8Jds6Esr48
+JVcTv7QT+7r05YpNZi8VKWyzs+kaM17Lr9tXHQVxOIGY3UWO70LjJxpcD6vO
+U4Ob9LLcD3DvUZ9q1Wn6mSj6Bb2rzNa4G5VN5Cv9v6HzcYQwy7ULagwqxKzy
+VAVf0jsYZ/O3bjUwtBQq5wsm/2PMmpoj7pnKr+hcb8Nlo2A1ginECQlMkeSe
+Hz6287B45QF+PAmrDgyTpeKUfwJtrn8Thx61D8Vk822y+YTsC7KYefRSrrj2
+8UTA4kD6u++hKwajlf4N9MeQt7imIBQCP11J+XPcFbWBJzgyt4mjPW9v4Lg6
+uYFBc3ADJzZw6tGOawwkjF5sj6BsxTaPWIOIwe84vVMGPTkvcAbvJzy+4q7a
+VapUf0YmvV79C9oPyKTWq1vQphTQCf7/qCLpuCe3ovalcvo/KObobytWaitW
+wll8yDpztHOK1AdR+XPIJVR7o6Ik9gSjc2ITH/+CscdRJIXb0dSp+focNyjy
+KK2L3O9E5WdIGbQFrrCvn9xBysJVC59aGIdFExMWPsMkEwJMYfoOzADdAa4F
+MKI1G6hIMUBPgH0BzkTBswFqAQYi++J/Kz3doBgJAAA=
+""",
+            """
+androidx/test/OuterComp$InnerObject.class:
+H4sIAAAAAAAA/41US08TURT+7p0+ptMC5SEUUHxQtFClBXVhICZIfAwpxQjB
+KKvbdoSh7QzO3BKWrPQfuHDpwhULiQsSTQzKzp/kwnjuMApCMCbtOd8597zm
+O3fm+89PXwDcwm2GYeHUPNeubRWk5cvCQkta3qzb3MiajmN5C5V1qyrjYAzp
+dbEpCg3hrBZ+ezWG2LTt2PIug5YbXU4hipiBCOIMEblm+wwjpf+oP8WgS3dR
+erazytCTGy0d9Tr0UsRwyfVWC+uWrHjCdvyCcBxXCmm7hMuuLLcaDYpKHiur
+o50Krwl/bdatWcGIpnbn4esfNLb1siUaNN+5XOnkc02NPmfI/qsbtRKVhkXt
+oq5cszyGrtNVqPV0tRGwY4ArSnSzvLg0U569n8IAjAQ5Bxk6S3VXUlhh3pKi
+JqSgRN7c1Gg/TImEEmBgdfJv2coqEqpNMLzY3x4yeIYbPL2/bXBdgWSodUO5
+0u36wSsjs789yYvsXlzn397FeJrPdae1AV6MTOrp6EAkw4rs0cEbbS6RjpE3
+TpgR1gknFFbdJpmaoe+MXcYxyhBfIt94XTIMPmk50m5aprNp+zYRNXNEHl2M
+w2V0lGzHKreaFctbUmQqDt2qaCwLz1Z26GxblKJanxcboZ09Wfux8ETTokH+
+apIKrsFsQ/i+Raax6La8qvXAViX6wxLLp4bDBO0kEtDdr1ZE+jpZMdJtpKN0
+Gg2sG2QV1FKUd2wP+i4BjvEwGMjRMZA6DECCSqmiSfLwIPlymKx1dXwIjo7C
+tTD8eGd6+9AZ9j1K7do5I5WhGz1hJ5M0J903ln+PaGQn/xX8LaLaTn4f/Glk
+Jxi8SDICHteDYr2HCWExhXrpz4gdqGtMLw0BHZk/VPQFCUDyM/izPfR/xPnd
+wKFhkqTikWMM7cTqzaBfnr49ajSGC0TP0Ao0ExdNXDLp6a4QxLCJLEZWwHxc
+xbUVGL765XzEfHQHoNdHOgBJkr8Ar2VkytEEAAA=
+""",
+            """
+androidx/test/OuterComp.class:
+H4sIAAAAAAAA/31RW2sTQRT+ZjbJbjaxTeMlibX10lqbCm5bfKpFqEVhIaZg
+Q0DyNEmGOslmV3YnoY958of4D4oPBQUJ+uaPEs9so0Wk7rDnO9fvzDnz4+fn
+rwCe4jFDRYT9OFL9U0/LRHtHYy3jw2j03gZjKA3ERHiBCE+8o+5A9rQNiyG3
+r0KlnzNYm/V2EVnkXGRgM2T0O5Uw1BpXcD5jcPZ7QVrtgpsSx28etw6ahy+L
+uAY3T84FhrVGFJ94A6m7sVBh4okwjLTQKiK9GenmOAiIaqkxjDSRea+lFn2h
+Bfn4aGLRZMyIvBFgYEPynypjbZPW32Goz6ZFl1e5y0uzqcsdy/n+gVdn012+
+zfa4lXlhO/zbxxwvcVOwywzNgh+GNEYgksTMwlBIHRd7Ydi4Yub1v8ts3KX5
+/pv7e9P3GewWxZ8MiX75zTjUaiT9cKIS1Q3kweVOaPGHUV8yLDZUKJvjUVfG
+LUE5DOVG1BNBW8TK2HNn8fJKkord42gc9+QrZWK1eZ/2P12wQ4+TSTdaM29F
+uE5WjrBEyOlkU+shWZ7ZO2F26xzOWRremCcDj+gAxYsE5IkKcFD4U1yhbPMV
+voC/PUfxExbPUoeFTZJlCt+jf4Xu8YBwlbCetljDFuEe0SwRcbkDy8d1Hzd8
+3MQtUlHxUUWtA5bgNpY7yCZwE9xJkEuwkmD1F4DlAzIZAwAA
+""",
+            """
+androidx/test/TestAbstract.class:
+H4sIAAAAAAAA/3VRy04CMRQ9t8AgIwriC/AR3Rh14ahxpzFBExMS1EQNG1eF
+mWgFOsm0EJd8i3/gysSFIS79KOPt6NbNyXnctqft1/f7B4AjrBHqUodJrMLn
+wEbGBncMjY6xiezaPIhQfpIjGfSlfgiuO0+RczME70RpZU8Jme2ddhE5eD6y
+yBOy9lEZwmrr/22PCXOtXmz7SgeXkZWhtJI9MRhluBQ5KDgAgXrsPyun9pmF
+B4SNydj3RVX4osxsMp7aqk7Gh2KfznKfL54oCzd3SG513p2617Pc6jwOI0Kp
+pXR0NRx0ouROdvrsVFpxV/bbMlFO/5n+bTxMutGFcqJ2M9RWDaK2MorThtax
+lVbF2mQ3IfjSf03dGzBWWQWpBnK7b5h6ZSJQY/RScx11xuLvAArw03wlxWWs
+pt9CmOaseI9MEzNNzDZRQpkp5pqoYP4eZLCARc4NfIMlA+8H7YuiztMBAAA=
+""",
+            """
+androidx/test/TestAbstractComp$Companion.class:
+H4sIAAAAAAAA/5VSTW/TQBB9u07jxARIWz4SPspXkNJK1E3FrQipBCFZSkGC
+Kpce0MZZYBN7jbzrqMec+CH8g56QOKCoR34UYtYJcENwmZ15b96M962///j6
+DcBjPGToCj3OMzU+Da00NjymcDgyNhex7Wfpx44LQqtM+2AMzYmYiTAR+n34
+ajSRsfXhMVSfKK3sUwavuz1sYA3VABX4DBX7QRmGncG/Ljlg6HUH08wmSoeT
+WRoqbWWuRRI+l+9EkVC7Jl0R2yw/EvlU5gfbwwDcLdvsxH/It2nJMuz+3zSG
+9V+CI2nFWFhBGE9nHhnGXKi7AAY2JfxUuWqPsnGPobOYBwFv8YA3KVvMa+ef
+vNZivs/32DO/xs8/V3mTu9595iZs/d0VHzcZ6r+tYfBdx+7Ukq/9bCwZLg+U
+li+LdCTzYzFKCNkYZLFIhiJXrl6BjUhrmfcTYYyk1wjeZEUeyxfKce3XhbYq
+lUNlFDUfap1ZYWmdQY9srbi70sndo9In36EqdJenc23nC2pnJX2XYrUEe7hH
+sbFsQB0B0GSUXViJH9HJV+LGWWmkE1xbgktBmV3EJeI83KcqKEW3cBttPCgX
+bqFT/sDkAfU2T+BFWI+wEWETVyjF1YhmXj8BM2ihTbxBYHDDoPoTIO6Wpv0C
+AAA=
+""",
+            """
+androidx/test/TestAbstractComp.class:
+H4sIAAAAAAAA/4VRXWsTQRQ9s5vPdWOT+pVYramtMc2D2xRBsEWoEWEhTUFL
+QPI0ScY6yWZWdiahj/kt/oPiQ0FBgo/+KPHuNrYPQn25Z+6dc889c+fX728/
+ADxHg2Gdq2EUyuGpZ4Q23jGFg742ER+YVjj5nAVjKI74jHsBVyfeUX8kBiYL
+myGzL5U0rxjs+nbXRRoZBylkGVLmk9QM1fb10nsMuf1BsBSpX0/eigNXMlRZ
+uAzNenscGur1RrOJJ5URkeKB90Z85NOAGhR1TgcmjA55NBbR3oXBmw4KWGHI
+X4oxNP7j8mrwnosSVvOwcIthsx1GJ95ImH7EpdIeVyo03BBNe53QdKZBQO8r
+/XV5KAwfcsOpZk1mNi2fxSEfBzCwMdVPZZzt0GnYZKgt5q5jlS3HKi7mjpWz
+crXyYl61d60d9pLZr9M/v2SsohWzd1mskY2dPxsbhrV3U2XkRPhqJrXsB+Lg
+yhz9TiscCoaVtlSiM530RXTMicOw2g4HPOjySMb5suj6SomoFXCtBTU778Np
+NBBvZXxXWc7p/jMltUFbSiVPq8RLI9ykLEN4h9AiTCfZFmVevADCdOMcubPk
++smSDDRRo+heEJCHQ5jDjcvmMpIVwv2Owgd2juJX3D5LKjaeUnSIVyDFEhmp
+J9qPsU34gup3SfFeD7aPso+Kj/tYoyMe+HiI9R6YxiNUe0hpOBobGhmN0h/c
+zA/4OwMAAA==
+""",
+            """
+androidx/test/TestClass.class:
+H4sIAAAAAAAA/3VRu04CQRQ9d5BFVpQFX+CrVgsXjZ3GRE1MSFATNTRWA7vR
+gWU2YQZCybf4B1YmFoZY+lHGO6utzcl53Jk5N/P1/f4B4BjbhHWpo2Gqoklo
+Y2PDB4bLRBpTABGCnhzLMJH6Kbzt9OKuLSBH8E6VVvaMkNvda5eQh+djDgXC
+nH1WhlBv/XPnCaHS6qc2UTq8jq2MpJXsicE4x3XIQdEBCNRnf6KcajCLDgk7
+s6nvi5rwRcBsNq3NpkeiQRf5zxdPBMJNHZE7W3APHvQtF7pMo5hQbikd34wG
+nXj4IDsJO9VW2pVJWw6V03+mf5+Oht34SjlRvxtpqwZxWxnF6bnWqZVWpdrg
+EIL3/evp1messQozDeT33zD/ykSgzuhl5hI2GEu/AyjCz/LNDNexlX0HYYGz
+0iNyTSw2sdREGQFTVJqoYvkRZLCCVc4NfIM1A+8HjoCWJ8sBAAA=
+""",
+            """
+androidx/test/TestClassComp$Companion.class:
+H4sIAAAAAAAA/5VSTW/TQBB9s07jxARIWz4SyjepaJGom4pbERIEIUVKQYIq
+lx7QJllgE3uNvJuox5z4IfyDnpA4oKhHfhRi1ilwQ3CZnXlv3oz3rb//+PoN
+wCNsEjalGeWZHh3HTlkXH3LoJNLaTpZ+bPkgjc5MCCLUx3Im40Sa9/GrwVgN
+XYiAUH6sjXZPCMHWdr+GFZQjlBASSu6DtoT7vX/asE9ob/UmmUu0icezNNbG
+qdzIJH6u3slp4jqZsS6fDl2WH8h8ovL97X4E4Tett4Z/yLdpwRJ2/m8aYfWX
+4EA5OZJOMibSWcBWkQ9VH0CgCePH2le7nI3ahNZiHkWiISJR52wxr5x+ChqL
++Z7YpWdhRZx+Lou68L175Cds/MWSEBuE6m9fCKGndyaOHe1kI0W42NNGvZym
+A5UfykHCyFovG8qkL3Pt6zOw1jVG5cVcxe8Qvcmm+VC90J5rvp4ap1PV11Zz
+81NjMicdr7Nos6clf1E+hX9O/t5bXMX+5nyuPPiCyklB3+ZYLsB7uMOxtmxA
+FRFQJ87OnYkf8inOxLWTwkUvuLIEl4IiO48LzAW4y1VUiK7jBpq8wC+8iVbx
+37IH3Fs/QtDFahdrXazjEqe43OWZV49AFg00mbeILK5ZlH8CxwhM7PQCAAA=
+""",
+            """
+androidx/test/TestClassComp.class:
+H4sIAAAAAAAA/31RXWsTQRQ9s5vPdWOT+pVYq9WmNu2D2xRBMEXQiLCQtqAl
+IHmaJGOdZDMrO7Ohj/kt/oPiQ0FBgo/+KPHuNrYPQl7umXvn3HPP3Pn95/tP
+AM+xy7DG1TAK5fDMM0Ib74RCO+Bat8PJlzwYQ3nEp9wLuDr1jvsjMTB52Ay5
+A6mkecVgN3a6LrLIOcggz5Axn6VmWO8s0W0xFA4GwUJhawmzngSuZKjycBma
+jc44NNTojaYTTyojIsUD7634xOPAtEOlTRQPTBgd8mgsotaltZsOSlhhKF6J
+MWwv83c9teWigtUiLNxi2OyE0ak3EqYfcam0x5UKDTdE095RaI7iIKCXVf5Z
+PBSGD7nhVLMmU5sWzpJQTAIY2JjqZzLJ9ug0bDLU5zPXsaqWY5XnM8cqWNX5
+bMPet/bYS2a/yf76mrPKVsLdZ4lCPjH9bGzoE9/HysiJ8NVUatkPxOtra/Ql
+7XAoGFY6UomjeNIX0QknDsNqJxzwoMsjmeSLousrJaJ0F4KanQ9hHA3EO5nc
+1RZzuv9NQZN2lEkfVktWRrhJWY7wDqFFmE2zOmVe8nzC7O4FCufp9daCDGp7
+StG9JKAIh7CAG1fNVaQLhPsDpY/sAuVvuH2eVmxsU3SIVyLFChlppNpPsEP4
+gup3SfFeD7aPqo+aj/tYoyMe+FjHwx6YxiNs9JDRcDQea+Q0Kn8BDq7wpy0D
+AAA=
+""",
+            """
+androidx/test/TestClassWithArg.class:
+H4sIAAAAAAAA/31QTWsTURQ9781nxsRM4leaaq3aRZtFJy3ulGIMCANRoZZ0
+kdVLZkhfM5mBeS+ly/wW124ERXAhwaU/SrwvDa5EeJx7z32Hcz9+/f7+A8Bz
+7DHsiDwpC5lcRzpVOjoj6GdCqXOpL3rl1ANjCC/FlYgykU+j9+PLdKI9WAzu
+S5lLfcJg78cHQwZr/2BYhQMvgA2fuCinDCyuIsCtCjiqJNUXUjHsDv7f9QW5
+T1PdMwZkGzM0BrNCZzKP3qZaJEILkvD5lUVrMAMVA6B2M6pfS8O6lCVHDP3V
+shnwFg94uFoG9HjoB9y3WqvlMe+y17WmG/I271o/P7o8tE8bf5lP6rbtO6Fr
+rI6ZaeCZWQ9nmnbpF0nKUB/IPH23mI/T8kyMM6o0B8VEZENRSsM3xeBDsSgn
+6RtpyNbpItdyng6lkvTby/NCCy2LXOGIDmWvV2mau1HGKXfgEj4mdkKcUww6
+31DpbH9F7fNas0toNECIJ4T3b1S4jbq5DGXGjQ5J/42NV2QORtHpfEHt0z9t
+qjeCjQ3H0zXu4BnFV+shHdwZwYpxN8a9mNo+oBStGFtoj8AUtvFwBE+hrvBI
+IVijqxAqNP4AZEwrjogCAAA=
+""",
+            """
+androidx/test/TestClassWithArgComp$Companion.class:
+H4sIAAAAAAAA/5VSTW8TMRB99qbZZAmQtnwkfLdNpRZBt6m4FSGVIKRIKUhQ
+hUMPyElM62TXi2wn6jEnfgj/oCckDijqkR+FGG8CHFEv45n35s14n/fnr+8/
+ADzDJsMToQcmU4Oz2Enr4iMKrURY+0G50wNz0srSzw0fhFaZDsEYqkMxEXEi
+9En8tjeUfRciYCg+V1q5FwzB1na3giUUIxQQMhTcqbIMO53LLNpnaG51RplL
+lI6HkzRW2kmjRRK/kp/EOHGtTFtnxn2XmUNhRtLsb3cjcL9wtdH/R35Mc9bv
+v9Q0huU/gkPpxEA4QRhPJwEZx3wo+wAGNiL8TPlql7JBk6Exm0YRr/GIVymb
+TUsXX4LabLrHd9nLsMQvvhZ5lfvePeYnrP/fmRB3Gcp/7WEIfdfOyJG/rWwg
+Ga53lJZvxmlPmiPRSwhZ6WR9kXSFUb5egJW21tLk4yW9SvQ+G5u+fK08V383
+1k6lsqusouYDrTMnHK2zaJK1Bf+9dHL/uHTth1TF3gA6lx5/Q+k8px9RLObg
+JtYoVuYNKCMCqoyyKwvxUzr5Qlw5z830gltzcC7Is6u4RlyAdaqiXHQP91HH
+Rr7wARr5z0weUG/1GEEby22stLGKG5TiZptm3j4Gs6ihTrxFZHHHovgbuLwQ
+4QkDAAA=
+""",
+            """
+androidx/test/TestClassWithArgComp.class:
+H4sIAAAAAAAA/41SW08TQRT+ZnvZ7VpkqYgFvCAXLRXZQnwSQoI1xk1KTZDU
+GJ6m7Vi23c6a3WnDI7/FZ1+IGhJNDPHRH2U8s63woAkmu+fMOXPO953L/Pz1
+9TuAJ9hgWOSyHYV++9hVIlbuAYlqwOP4ja+OdqNONey/N8EYnC4fcjfgsuO+
+anZFS5lIMWS3femrHYZ0yVttMKRKq408MjBtpGGRzaMOA/PysHEtBwN5ClVH
+fsywXLuaeYsYOkLtahCC9his7VYwply7On9ZCy79UJq4wbBRqvVCRflud9h3
+falEJHngPhfv+CBQ1VDGKhq0VBjt8agnoq1RLzdtTGOGIXcBxrD+H8Vfkm/l
+UcSsbn+OYakWRh23K1Qz4r6MXS5lqLiisNith6o+CAJqe+pPpXtC8TZXnHxG
+f5iitTEtclqARtsj/7GvrQqd2rTRl+cnBdsoGrbhnJ/Y9BmOZRtWunh+smBu
+GhX2lJnPJgpZx5gzKqkfH7KGk96furAsSplLWxknq/E2mWYxdX/rPcUwvz+Q
+yu8LTw792G8GYveyfFptNWwLhsmaL0V90G+K6IBTDEOhFrZ40OCRr+2xM+9J
+KaJkbIKS7dfhIGqJF76+mx3zNP5iwQbNMU39GpjVY6XyymRlSd8mXdAvjXSK
+7EzifUTWDkUbpO3yGXLl+S+YOE0Q1saZwAoek5wZReE6JvV86aTRaB1w6B9h
+uXrspDPlz5j4+E+Y/ChgDGNRUeY4uYhkcch/w/RbdoZbnzB/mnhSWE8IGb02
+I2nMTbBXUSFdJf8dQrx7iJSHex4WPNzHIh2x5GEZK4dgMR7g4SGsGJMxSjHs
+RGZjODGmYhR/A+R3KVn3AwAA
+""",
+            """
+androidx/test/TestGraph.class:
+H4sIAAAAAAAA/3VSTW/TQBB9s/mw4waalo8klO/2UDjgtuJGhVQqQJaMkWgU
+qeppE6/aTRwb2Zuox5z4IfyDikMlkFAEN34UYtZEcEB4pTfzZt887Yz84+fn
+rwCeYovQlmmcZzo+940qjN9jeJ3L92cOiNAayZn0E5me+m8HIzU0DiqE+r5O
+tXlOqGw/6jdRQ91DFQ6has50QeiG//F8RnD3h0nZ7UHYFjeIjnoH0eHLJq7A
+a3DxKmEzzPJTf6TMIJc6LXyZppmRRmecR5mJpknCVmvhODNs5r9RRsbSSK6J
+yazCk5GFhgUQaMz1c23ZDmfxLmFrMfc80RGeaHG2mLvfP4jOYr4nduiF44pv
+H+uiJax2j6yDYyd4MjaEjXfT1OiJCtKZLvQgUQd/n8bzH2axIqyGOlXRdDJQ
+eU+yhrAeZkOZ9GWuLV8WvaNsmg/VK21Jd2nc/8cWu7yUajlJ1+6I411mdY4t
+joJPrWT3mPl2Xo61x5dwL8rr+0sxuPUBY/O3AA3mgIuVP81tVttv5QvE8SWa
+n7B6URYEHpZ4B5vlb8O7Z4P1E1QCXAtwPcAN3OQU7QAddE9ABW5hg+8LeAVu
+F6j/Ai/P7yRzAgAA
+""",
+            """
+androidx/test/TestInterface.class:
+H4sIAAAAAAAA/32Oz0rDQBDGv9lo08Z/qVqoiK9g2tKbJy9CoCKoeMlpm2xl
+m3QD2Wnpsc/lQXr2ocSJ3p2Bb76Zgd/M1/fHJ4ApBoRr7YqmtsU2YeM5eRVJ
+HZtmoXMTggjxUm90Umn3njzNlybnEAGhPytrrqxLHg3rQrO+I6jVJhAstdJr
+BQQqZb61bTcSV4wJg/2uG6mhilQsbjHc7yZqRO1yQriZ/fOP3BBk2M5uSyZE
+L/W6yc2DrQzh6nnt2K7Mm/V2Xpl752rWbGvnO8LGAf5C4eJXz3EpdSy8Q8lO
+hiBFmKKboodILI5SHOMkA3mc4iyD8og9+j/Vk+x/PAEAAA==
+""",
+            """
+androidx/test/TestKt.class:
+H4sIAAAAAAAA/4VUbU/TUBR+bjvWrgzW8b6BiLzo5gsFfBc0ISQmjRMSJBhC
+YtJt11kYbdJ7R/jIb/EXqHwgkcQQP/qjjOc2xGkLug/3nvvc53l6zunpfvz8
++g3AAzxnGPKCZhT6zSNHciGdLVpeSQOMwd7zDj2n7QUtZ6O+xxuE6gyDLS7X
+2p4QbiCkFzT4Jn/PMF6p1tJGMW+ZYaYWRi1nj8t65PmBcLwgCKUn/ZDi9VCu
+d9ptYtmNlG3pStM8TORy0GAxlJMpvfXlh9WoFVtMX53ZBY0ePdq4Sj71P3Ee
+/SioRGyGMUrEDQIepRuUTmOjI3k026VTGsP+5eJkEilpHkMYVkmMMJgrjbYf
++PIFg16pblNxV1RgoMyQXYm5eUygZGEc1xgm/12xgesMmYpb3VaiGxamMJ0S
+JTM0MGthThGLtf1QUoLOay69pic9qls7ONRpHplacmoBA9tXgUaXR76KFihq
+LjK8Oz8uW+fHljamWZqpJ3ZtumgTQVtg3z9mTeKVM6Zm64RmCOzpglnbINAk
+MNcFLbtXPWWJpvyScgzcZ7C6NTEYqjfz+5Lmf7MTSP+Au8GhL/x6m692R5y6
+tRY2OUOh5gd8vXNQ59GWRxyGfNeNE896E3aiBn/pq7vSheV2yhCL9KYz1BMd
+ZfUZULce0ylLu0F7WU1kCqMBSWAZlNBDJw1P6DRBqPplvqD3U/wGnl5wFfNP
+XQl59KVVxaQqm1ANYDCtGk2qzL9UJsZIyWLVGuLRwMwZxndOMXmC3jNM7diF
+U8ycoHiGuTi+eYLRz79N+2NRBhZZjpCdjmd0tuh2jv7/HpL5shozPMIK7RuE
+36KmVHahu6i6uO3iDu66uId5Fw4WdsFU+5d2kRcwBXICPQJZgX6BglBgn8CQ
+wLDAgMDgL1Y9gwBpBQAA
+""",
+            """
+androidx/test/TestObject.class:
+H4sIAAAAAAAA/3VSTWvbQBB9s7ZlWXEbN/2InfQrH4ekhyoJvTUUktCCQFWh
+MYaQ09pa0rVlCaS1ydGn/pD+g9BDoIVi2lt/VOmscNpDqRbezHs789gZ9PPX
+l28AXmCb0JZpnGc6vvSNKozfZXjXH6qBqYMIraGcSj+R6YV/o1YIzqFOtXlF
+qOzs9pqowfFQRZ1QNR90QVgL/2f6kuAeDpKy3YOwPW4QnXaPopPXTdyC12Dx
+NmErzPILf6hMP5c6LXyZppmRRmecR5mJJknCVnfCUWbYzH+rjIylkayJ8bTC
+s5GFhgUQaMT6pbZsj7N4n7A9n3meaAtPtDibz9wfH0V7PjsQe3Rcd8X3T45o
+CVt7QNahbkd4PjKE9feT1OixCtKpLnQ/UUd/n8YLOMliRVgOdaqiybiv8q7k
+GsJKmA1k0pO5tnwheqfZJB+oN9qSzsK4948t9nkp1XKSjt0Rx8fMHI4tjoJP
+rWRPmPl2Xo61Z9dwr8rrp4tioImNEssCNNgKcLH0p3mVq+239BXi7BrNz1i+
+KgWBzRIfYav8cXj3bLByjkqAuwHuBbiPB5xiNUAbnXNQgTWs830Br8DDAs5v
+jU1b0HUCAAA=
 """
+        )
+        .bytecode
diff --git a/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongNavigateRouteDetectorTest.kt b/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongNavigateRouteDetectorTest.kt
index 4af2ebc..ce9918d 100644
--- a/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongNavigateRouteDetectorTest.kt
+++ b/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongNavigateRouteDetectorTest.kt
@@ -17,28 +17,21 @@
 package androidx.navigation.runtime.lint
 
 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest.compiled
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin
-import com.android.tools.lint.checks.infrastructure.TestFile
 import com.android.tools.lint.checks.infrastructure.TestMode
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
+import org.junit.runners.JUnit4
 
-@RunWith(Parameterized::class)
-class WrongNavigateRouteDetectorTest(private val testFile: TestFile) : LintDetectorTest() {
+@RunWith(JUnit4::class)
+class WrongNavigateRouteDetectorTest : LintDetectorTest() {
 
     override fun getDetector(): Detector = WrongNavigateRouteDetector()
 
     override fun getIssues(): MutableList<Issue> =
         mutableListOf(WrongNavigateRouteDetector.WrongNavigateRouteType)
 
-    private companion object {
-        @JvmStatic @Parameterized.Parameters public fun data() = listOf(SOURCECODE, BYTECODE)
-    }
-
     @Test
     fun testEmptyConstructorNoError() {
         lint()
@@ -47,7 +40,8 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -57,7 +51,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .skipTestModes(TestMode.FULLY_QUALIFIED)
             .run()
@@ -72,7 +67,8 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -98,7 +94,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .skipTestModes(TestMode.FULLY_QUALIFIED)
             .run()
@@ -113,7 +110,8 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -150,91 +148,92 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .skipTestModes(TestMode.FULLY_QUALIFIED)
             .run()
             .expect(
                 """
-src/com/example/test.kt:7: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:8: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClass)
                                    ~~~~~~~~~
-src/com/example/test.kt:8: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:9: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClass::class)
                                    ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:9: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:10: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClassWithArg)
                                    ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:10: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:11: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClassWithArg::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:11: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:12: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestInterface)
                                    ~~~~~~~~~~~~~
-src/com/example/test.kt:12: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:13: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestInterface::class)
                                    ~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:13: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:14: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = InterfaceChildClass)
                                    ~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:14: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:15: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = InterfaceChildClass::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:15: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:16: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestAbstract)
                                    ~~~~~~~~~~~~
-src/com/example/test.kt:16: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:17: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestAbstract::class)
                                    ~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:17: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:18: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = AbstractChildClass)
                                    ~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:18: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:19: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = AbstractChildClass::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:19: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:20: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = InterfaceChildClass::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:20: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:21: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = Outer.InnerClass)
                                    ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:21: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:22: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = Outer.InnerClass::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:24: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:25: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClassComp)
                                    ~~~~~~~~~~~~~
-src/com/example/test.kt:25: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:26: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClassComp::class)
                                    ~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:26: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:27: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClassWithArgComp)
                                    ~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:27: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:28: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestClassWithArgComp::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:28: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:29: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = OuterComp.InnerClassComp)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:29: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:30: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = OuterComp.InnerClassComp::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:30: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:31: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = InterfaceChildClassComp)
                                    ~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:31: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:32: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = InterfaceChildClassComp::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:32: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:33: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = AbstractChildClassComp)
                                    ~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:33: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:34: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = AbstractChildClassComp::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:34: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:35: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestAbstractComp)
                                    ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:35: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
+src/com/example/test.kt:36: Error: The route should be a destination class instance or destination object. [WrongNavigateRouteType]
     navController.navigate(route = TestAbstractComp::class)
                                    ~~~~~~~~~~~~~~~~~~~~~~~
 27 errors, 0 warnings
@@ -242,528 +241,3 @@
             )
     }
 }
-
-private val SOURCECODE =
-    kotlin(
-            """
-
-package androidx.navigation
-
-public open class NavController {
-
-    public fun navigate(resId: Int) {}
-
-    public fun navigate(route: String) {}
-
-    public fun <T : Any> navigate(route: T) {}
-}
-""" +
-                TEST_CLASS
-        )
-        .indented()
-
-private val BYTECODE =
-    compiled(
-        "libs/StartDestinationLint.jar",
-        SOURCECODE,
-        0xb1569275,
-        """
-                META-INF/main.kotlin_module:
-                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgUuMSTsxLKcrPTKnQy0ssy0xPLMnM
-                zxPi90ssc87PKynKz8lJLfIu4RLl4k7Oz9VLrUjMLchJFWILSS0u8S5RYtBi
-                AADcysPxVwAAAA==
-                """,
-        """
-                androidx/navigation/AbstractChildClass.class:
-                H4sIAAAAAAAA/41QTW9SQRQ9M+8DeAV54Belamv9CGUhtHGnaaQkJiTYRW1Y
-                wGrgvdAJj/eSNwPpkt/i2o2JxsSFIS79UcY7j2pcsHAxZ+65c3LunfPz17fv
-                AF7iGcNzEQdpIoPrViyWciq0TOJWZ6x0Kia6eyWjoBsJpXJgDAfbtJeh0n/0
-                OVgM7msZS33KYDeGRwMGq3E0KMJBzoONPHGRThnYsAgPOwVwFEmqr6RiaPT/
-                b5tXNGUa6o4xIvshQ6U/S3Qk49a7UItAaEESPl9a9E1moGAANHZG/WtpWJuq
-                4JjhbL2qerzGs7Needzf8Xjeqq1XJ7zNzkpV1+d13rZ+fHC5b19U/rI8qet2
-                3vFd43TCcLh1/X8Doq1oCf9cLLtJrNMkisL0xUxTAN0kCBnKfRmH54v5OEwv
-                xTiiTrWfTEQ0EKk0/KbpvU8W6SR8Kw3ZvVjEWs7DgVSSXjtxnOhsssIxpWtn
-                /66asKniVDtwCQ+InRLndHvNryg0976g9CnTPCY0GqCBQ8J7GxVuoWxipMq4
-                Uerw6Wy8WiZdup3mZ5Q+brUpbgQ3NhxPMtzHU7rfZEs6uD2C1cOdHu72aOx9
-                KlHrYRf1EZjCHh6MkFMoKzxU8BQeKbgKvkLlN2AWm1jVAgAA
-                """,
-        """
-                androidx/navigation/AbstractChildClassComp$Companion.class:
-                H4sIAAAAAAAA/51Sy27TQBQ9Y6dxYgKkLY+E9yNIbSXqpqrYBCGVIKRIaZEo
-                yqYLNLGHdhJ7Bo0nUZdZ8SH8QVdILFDUJR+FuOME2AKb+zr33Ds+199/fP0G
-                YA9PGPa4SoyWyVmk+FSecCu1ivaHuTU8tt1TmSbdlOd5V2cfW85wRQ0BGEN9
-                xKc8Srk6id4MRyK2AXyG8nOppH3B4G9sDmpYQTlECQFDyZ7KnOFZ/38Wdhja
-                G/2xtqlU0WiaRVJZYRRPo1fiA5+ktqsVTZjEVpsDbsbCdDYHITy3eL0V/wHf
-                ZwXKsP1v0xhWfxEOhOUJt5xqXjb1SUjmTNUZMLAx1c+ky3YoStoMrfksDL2G
-                F3p1iuazysUnvzGf7Xo77GVQ8S4+l72653p3mZuw9fcKBbjNUP0tEx3lkE/p
-                9dboNBVme2xJ+K5OBMPVvlTicJINhXnHhylV1vo65umAG+nyZbHWU0qYYoGg
-                c4VHemJi8Vo6rPl2oqzMxEDmkpr3ldK2eF2ONmldcgKQ99zV6TvuUxY5Rciv
-                bH1B5byAH5AtF8UOHpKtLRpQRQjUGUWXluSn5L0luXZeqOsINxbFBaGILuMK
-                YT4eURYWpDu4iyYeFwvvoVX87aQB9daP4few2sNaD+u4RiGu92jmzWOwHA00
-                Cc8R5riVo/wTjWwvPCoDAAA=
-                """,
-        """
-                androidx/navigation/AbstractChildClassComp.class:
-                H4sIAAAAAAAA/5VSS08TURT+7vQ1HYqUiljABwpiqcgUQlxYQoI1mialCyRN
-                hNVtey2XTu+YubcNS36LazdEDYkmhrj0RxnPTCskygIXc849Z77znefPX1+/
-                A9jAOkORq3bgy/axq/hAdriRvnK3m9oEvGUqh9JrVzyudcXvvU+BMSxehd8T
-                2lzERMgYQ3JTKmm2GOKF/eUGQ6yw3MgggZSDOGyyedBhYPsZOBhLw0KGoOZQ
-                aoaV2vWrKlOmjjDbIRml2GewN1veKPXG9XkWQ8EVAVK4ybBWqHV9Qzzu0aDn
-                SmVEoLjnvhTveN+jJhVx9FvGD3Z40BVBedjbLQdTmGZIX5AxPPuPZi6LKGeQ
-                x0w4llmGhZofdNwjYZoBl0q7XCnfRDzarfum3vc8GsPkn4p3hOFtbjj5rN4g
-                RqtmoUiHAjTyLvmPZWiV6NVeY3h9fpJzrLwVfecnjpUdcyw7nj8/mU+tWyX2
-                nKVejOeSWWvWKsV+fEha2fju5IVlU8hs3E5kkyEdHdXSlS3/fSVUHlWTrfMB
-                jdMEvueJYLVrGOZ2+8rInqiqgdSy6Ynty37pRip+WzBM1KQS9X6vKYI9ThiG
-                XM1vca/BAxnaI2emqpQIogELCnbe+P2gJV7J8N/MKE/jnyxYo8HHaUAWZsI9
-                UJ1PyEqSvkM6F54s6RjZici7QtYWoS3STvEM6eLcF4yfRgxPR5FAGaskp4co
-                3MBEuBB6hWy0P2TpG3K54Z5IJ4qfMf7xSprMEDCisamo1Cg4j2jTyHzD1Ft2
-                htufMHcaeWJEHCZkdKZW1Fgp4i5Sw0CF/HeJ8d4BYlXcr2K+igd4SE8sVLGI
-                RwdgGkt4fABbY0KjoOFoLGskNbIakxr53/A96KpcBAAA
-                """,
-        """
-                androidx/navigation/AbstractChildObject.class:
-                H4sIAAAAAAAA/41Sy27TQBQ9M3k5bqChPJpQHqVFgrDAbcWOCilEIFkyRqJR
-                JNTV2B610zgzkj2JusyKD+EPKhaVQEIR7PgoxLUJD4kusOV759w5c67uGX/7
-                /vEzgCe4z/BA6CQzKjn1tJipI2GV0V4/ym0mYjs4VmnyOjqRsW2AMWxeRB7K
-                3P460ECFob6vtLLPGCoPe6MWaqi7qKLBULXHKmfoBf/Z8ymDsx+npZoLXkg4
-                fngw7IeDFy1cgtuk4mWG7cBkR96JtFEmlM49obWxpWruhcaG0zQlqSvB2FgS
-                815JKxJhBdX4ZFYhJ1gRmkUAAxtT/VQVaIdWyS41WMxdl3d4+S3mztd3vLOY
-                7/Ed9rzh8C/v67zNC+oew9aFw/3tEbVth2I2MNpmJk1l9nhsGTbeTLVVE+nr
-                mcpVlMr+nyHIuYFJJMNqoLQMp5NIZkNBHIa1wMQiHYlMFXhZdA/MNIvlS1WA
-                7lJ49I8sdsm+ajlzt3CT8h1CdcptypzeWonuEvIKZyjXHp3DOSu3N5dkoId7
-                FFs/CWiSFOBg5ffhdWIXz8on8LfnaH3A6llZ4Ngq421slz8k3RIJrB2i4uOq
-                j2s+ruMGLbHuo4PuIViOm9ig/Rxujls56j8AJAtPiM0CAAA=
-                """,
-        """
-                androidx/navigation/AbstractChildObjectComp.class:
-                H4sIAAAAAAAA/5VSW2sTQRT+ZnLbbKNN66WJVau2FC/otsU3gxCDwsK6gg0B
-                6dNsdmin2czI7iT0MU/+EP9B8aGgIEHf/FHi2TVU0L64y57bfOc7nG/2x8/P
-                XwE8xRbDI6Hj1Kj4xNNiqg6FVUZ73SizqRja3pFK4jfRsaTQjN/XwBi2Lmro
-                y8yeNxXIEkO1o7SyzxlK9x8MGqig6qKMGkPZHqmM4XHwH7OfMTidYVIwuuA5
-                jeOH+/1u2HvZwCW4dSpeZtgMTHroHUsbpULpzBNaG1swZ15obDhJEqJaCUbG
-                Epn3WloRCyuoxsfTEqnCclPPDRjYiOonKs92KIp3acB85rq8xYtvPnO+f+Ct
-                +WyP77AXNYd/+1jlTZ5D9xi2L1zwb61odDMU057RNjVJItMnI8uw/nairRpL
-                X09VpqJEdv8sQgr2TCwZlgOlZTgZRzLtC8IwrAZmKJKBSFWeL4ruvpmkQ/lK
-                5Ul7QTz4hxa7JGG52LudK0r+NmVV8k3ynN5KkW1Q5uXqkK88PINzWhzfWYCB
-                Du6SbfwGoE5UgIOl8+Y1QufP0hfwd2dofMLyaVHguFfYW9gsflC6KSJYPUDJ
-                xxUfV31cw3UKseajhfYBWIYbWKfzDG6GmxmqvwBXhfge3QIAAA==
-                """,
-        """
-                androidx/navigation/InterfaceChildClass.class:
-                H4sIAAAAAAAA/41Qz2sTQRT+ZvJjk21qNqnWNPVXrdomBzct3pRiGxACsUJb
-                ckhOk+yaTrOZhZ1J6DF/i2cvgiJ4kODRP0p8k4aCkIMs89775n37vTff7z8/
-                fgJ4hT2GPaGCJJbBta/EVA6FkbHyW8qEyUcxCJuXMgqakdDaAWPwrsRU+JFQ
-                Q/9D/yocGAcphp1VEhehNrcyDjIM2TdSSXPEkN7v1joMqf1apwAHeRdpuIRF
-                MmRg3QIKWM+D4w5RzaXUDLX2f275msYMQ3NslUi/y1Bqj2ITSeW/D40IhBFE
-                4eNpit7PbMjbAJo7ovtraVGDquCA4WQ+K7u8whdnPnO5t+byXKoynx3yBjtZ
-                L2c9XuWN1K9PWe6lz0q3KEfsajqX8bJW6ZBhd+X+/1hEa9EW3qmYNmNlkjiK
-                wuTlyJAFzTgIGYptqcLTybgfJheiH9FNuR0PRNQRibR4eemex5NkEL6TFmyd
-                TZSR47AjtaTusVKxWYzWOCB/0zQwS6dsDad3c6od5Cg+JXREmFN269+xVt/+
-                huKXBWeXov0LeEYfsHnDgoeSdZIqq0bGk+7GUsu3BlPO1L+i+HmlTOGGsJTh
-                eL6IO3hB+S317lLvXg+pFjZbuN9CBVtUotrCNh70wDQe4lEPjkZJ47FGQeOJ
-                Rk6jrLHxF0rwRpzxAgAA
-                """,
-        """
-                androidx/navigation/InterfaceChildClassComp$Companion.class:
-                H4sIAAAAAAAA/51Sy27TQBQ9Y6d5mABpyyPhXQhSC6JuKhBIRUgQhGQpLRJU
-                2XSBJva0ncSeQeNJ1GVWfAh/0BUSCxR1yUch7jgB1mVzX+eee8fn+uev7z8A
-                PMVDhmdcJUbL5CRUfCKPuJVahZGywhzyWHSPZZp0U57nXZ19bjvDFXVUwBga
-                Qz7hYcrVUfh+MBSxrcBnKL+UStpXDP76Rr+OJZQDlFBhKNljmTM87/3Xxh2G
-                znpvpG0qVTicZKF0DMXT8K045OPUdrXKrRnHVptdbkbC7Gz0A3hu82o7/gd+
-                ygqUYfN80xiW/xB2heUJt5xqXjbxSUrmTM0ZMLAR1U+ky7YoSjoM7dk0CLym
-                F3gNimbT6tkXvzmbbntb7E2l6p19LXsNz/VuMzfh8TkkquAmQ+2vTnSWPT6h
-                51uj01SYzZEl6bs6EQyXe1KJvXE2EGafD1KqrPR0zNM+N9Lli2I9UkqYYoGg
-                gwUf9djE4p10WOvDWFmZib7MJTW/Vkrb4nk5OiR2ySlA3nN3pw+5S1noJCG/
-                9OgbqqcFfI9suSi+wBrZ+rwBNQRAg1F0YUF+Qt5bkOunhbyOcG1enBOK6CIu
-                EebjPmVBQbqF22jhQbHwDtrFD08aUG/jAH6E5QgrEVZxhUJcjWjm9QOwHE20
-                CM8R5LiRo/wbyZhkAy0DAAA=
-                """,
-        """
-                androidx/navigation/InterfaceChildClassComp.class:
-                H4sIAAAAAAAA/5VSXU8TQRQ9sy3dtizSFsVS/ABBLUXYghiNEBKs0TQpNUHS
-                RHiatkPZdjtrdqYNj/wWn30hakg0McRHf5TxTqnwoInhYe+dc/fecz9//vr6
-                HcAa1hgWuWyGgdc8ciXvey2uvUC6ZalFeMAbonTo+c2Sz5UqBd33NhhDqs37
-                3PW5bLlv6m3R0DYiDLP/otkVSl9Q2RhhiG140tObDNH83kKNIZJfqDmwkUgi
-                iiRhHrYY2J4DB2MJWLhGrvrQUwxLlStUuk6pWkJvGTbKsccQ32j4w9xPrkA0
-                bwSX5GHjBsNKvtIJNBG57X7X9UyM5L77Uhzwnq9LgVQ67DV0EG7zsCPC9fPu
-                biYxiSxD4oKM4elV2rmsYt1BDtNmMrcY5ipB2HLbQtdD7knlcikDPSBSbjXQ
-                1Z7v0yDSf0reFpo3ueZks7r9CF0AMyJhBGjqHbIfeQYV6dVcYXh9dpxJWllr
-                8J0dJ63UaNKKR7NnxzP2qlVkz5n9YiwTS1k5qxj58SFmpaI76QsUp5BcND6S
-                ihm6VVPvf6+EaqNSUlXep2HqMPB9ES53NMP0Tk9qryvKsu8pr+6Lrctm6UZK
-                QVMwjFc8Kaq9bl2Eu5x8GDKVoMH9Gg89g4dGpyylCAfTFRScfBv0woZ45Zl/
-                U8M8tb+yYIWmHqXqYqSnzBrovUTTipG+QzpjjpZ0hLCNOMllQpvkbZFOFk4x
-                Wpj+gvETQhbcYSTwDEWSk+deSCFt9kEvw0brI96JIZdr1kR6pPAZ4x//SeOc
-                Owxp4riOxDA4i8Gi4XzD5Dt2iqlPuH0ysESoNZOQDYrIUXOrA+5HeEy6RPa7
-                xDizj0gZs2XcK2MO8/TE/TIe4OE+mEIeC/uIK6QVCgqOwqIyMKMwoZD7DYsK
-                p/5yBAAA
-                """,
-        """
-                androidx/navigation/InterfaceChildObject.class:
-                H4sIAAAAAAAA/41STW/TQBB9u0kTxw00LV8J5asUUOkBtxU3KqQSgWQpGIlG
-                kVBPG3tJN3F2JXsT9ZgTP4R/UHGoBBKK4MaPQsyaUA4gga2dmfd25u3O2N++
-                f/wM4DEeMGwJnWRGJSeBFlM1EFYZHYTayuytiGX7WKXJq/5QxrYKxtAYiqkI
-                UqEHwS+2xLDxN42uzO25ThVLDJV9pZV9ylDaetirowrPRxk1hrI9VjnDdud/
-                7/KEwduP00LOB3caXhgddg+i9vM6VlCvEdlg2OyYbBAMpe1nQuk8EFobW8jm
-                QWRsNElTklrtjIwlseCltCIRVhDHx9MSjYg5U3MGDGxE/IlyaIeiZJcOmM98
-                nzd5seYz7+s73pzP9vgOe1b1+Jf3Fd7gLnXP3eWfU6JzG5GYto22mUlTmT0a
-                WYb11xNt1ViGeqpy1U/lwe8uaHZtk0iGlY7SMpqM+zLrCsphWOuYWKQ9kSmH
-                F6R/aCZZLF8oB1oL4d4fstil+ZWp5Qqtlhso+TvUt8Nr5Dm99P0IbRAK3HDI
-                L22fwT8ttu8ukoH72CRb/5mAZYpAhRfOi69RtnuWP4G/OcPFD1g9LQiOe4W9
-                TRLuZ2W4RAKXj1AKcSXE1ZBKmxSiFeI61o/ActzATdrPUc9xK4f3Az/F2jnp
-                AgAA
-                """,
-        """
-                androidx/navigation/NavController.class:
-                H4sIAAAAAAAA/41SW08TQRT+Zttut8utrYJQQeWiFFC2EH2xhERJjEtqNdL0
-                hadpuynTbmeT3WnDY3+L/8AnjQ+G+OiPMp7ZNlBAo5vsuX/fnDNzfv769h3A
-                c+wzrHLZCgPROnckH4g2VyKQTpUPjgKpwsD3vTANxpDt8AF3fC7bzvtGx2uq
-                NBIM5oGQQh0yJIpb9WmkYNpIIs2QVGciYliv/JO9zGCNcx7hiu5WnSEVepHb
-                YmAuw3yxcnX2iQqFbJd1zXolCNtOx1ONkAsZOVzKQMUHRE41UNW+75c1U9BX
-                noUcw4NuoHwhnc6g5wipvFBy33GlZoxEM0rjDh3WPPOa3TH8Aw95z6NChs3J
-                JkYXUP5TW9OYx4KNu7jHkL9dcGOaMZGeZvmg9vJ25rBYq8Xp/O0cQ64ynuid
-                p3iLK04xozdI0NMyLTJagG6xS/Fzob0SWa09hvBiuGwbi4ZtZC+GtmFpg34r
-                Sdqif9ZaWLwY7hsl9jr145NJyeOVbKJglJJrlnUxzKa2KbVvZs2C8XZUkD6e
-                HRVQ1CKdmfCpqmTrk2nfdD812qdrS7DbVfT2R0GLVmCuIqRX7fcaXljjDd/T
-                wwdN7td5KLQ/Dm587Eslep4rByISFLp8rVdXi8CQORFtyVU/JIh9EvTDpvdG
-                aPzSGF8foSdAWIVBW6y/JHVLS01yhzxH9046tf0F1mcyDDwlacbBJJ6RnB4V
-                IAObdA5TcUSDX8T1NP5NoBkDF0bJMVBbM5glqSnmKKcpyqR1VXonn/+KxetE
-                JqwJovQlUZoolii/q23df3bcWAGJ/2G1/8q6THknrr5/nd1AKZbb2CNdoegK
-                XcmDUyRcPHTxyKUbXiMT6y428PgULMITbJ5iKoIdoRjBjLRNxlaEXIRChJnY
-                Lf4G70EG2roEAAA=
-                """,
-        """
-                androidx/navigation/NavControllerKt.class:
-                H4sIAAAAAAAA/41UW08TQRg9s1va7VJoy70F5Y6tFxbwLmhCmphsrCVBgiEk
-                Jtt2rAvLbLIzbXjkt/gLVB5IJDHER3+U8duV2NCC0IedmTPnnD3z9Zv99fv7
-                DwCP8JJh1hH1wHfrh5ZwWm7DUa4vrIrTKvlCBb7n8eCNSoAxZPaclmN5jmhY
-                G9U9XiNUZxhscFXyHCltIZUjanyTf2SYLhTLl/lucfmXvUovLvtBw9rjqho4
-                rpCWI4SvIpq0Kr6qND2PWJlal/nkNdYpGEgmocFkyHfGe++qT+tBIzIqXJfy
-                nEwxRmtXmSzczCKFfqTDUBmGMQplC8GD7sJdFWmjqXgw1xZRpGH3covLA3UZ
-                pDCE4TDQCIOxVvNc4apXDHqhuM1w679nSiDPEF+LFClMIGdiHLcY5m5SiQQm
-                GWIFu7gdSqdNTGHmCmln5gTmTMyH9Gx531cU2XrLlVN3lEP10A5aOjU1Cx/J
-                8AEGth9ONNo8dMPZEs3qywwfzo7y5tmRqY1ppmboHaM2k80QQVtiPz/HDeLl
-                Y4aW0QmNEdjTBuOZBIEGgck2aGZ6w7esMOSuPFQCDxnM9smozy9cucV9xTC+
-                2RTKPeC2aLnSrXp8vX1DqIQlv84Z0mVX8ErzoMqDLYc4DKm2LSee+c5vBjX+
-                2g33cueW212GWKZWiFGJdOTD+0PFe0qrOI0JGvNh+3Zh1EEdWAw59NBKwzNa
-                TRAa/mLf0Psl+kOen3OBvgu6HFKEdKmynap0h2oAg92q0U5V9oLKwBgpWaQq
-                IeoUzJ5ifOcEt4/Re4qpnUz6BLPHyJ5iPpovHGP06z/T/kjUB5PijJC5jhe0
-                Nml3nr6pj8l8New6PMEajRuE36GiFHah2yjauGvjHu7beIBFGxaWdsHC8q/s
-                IiVhSCQleiTiEv0SaRmCfRJDEsMSAxKDfwAPYTX9vQUAAA==
-                """,
-        """
-                androidx/navigation/Outer$InnerClass.class:
-                H4sIAAAAAAAA/41U31MbVRT+7m5+bJYENkBbfkRQiZiEtgvYai20CiiyGEIF
-                h7HiyyVZw8Kyi7sbpr44PPVP6Iy+OOM4PvFQZxQcO+Ng++bf5Diem90mNVSG
-                meSec8+e853vnnPu/euf3/8AcAPrDHnu1DzXqj3QHX5g1XlguY6+2ghML284
-                jukt2Nz3k2AM2g4/4LrNnbq+urVjVoMkZIbErOVYwV2GWMEobjDIheJGGnEk
-                VcSgMCiWQJnz6gzMSENFVwoS0uQfbFs+w3j5IgRmGLrqZmC0sCiNwaBW3b19
-                1zGdYIoAq+7+1wxF4nFRzLGy69X1HTPY8rjl+Dp3HDdoevt6xQ0qDdueEYdJ
-                qMT5MkNapMjXzC95ww4YtgoXS2QY5c7azVyQYxp96BfZh6iUgbseeJZDx+8v
-                FF+ADK10niudtvmGZddML4kRFaOiHf1t7MLzztxR8Bo1ku/vm06N4VrhLPTZ
-                bBEyERxDXoC/wZATpT/P8U3hWBCOC+c7loTjRBo5vCK0a3T4be5vL7g1kyHb
-                jjScwKyL802GA0gTpmNaxRTeohOZXzW4TTN2qfCS+n9Os39e+6n3fMs2qapx
-                N9g2PYbesyhEprzrBrbl6CtmwGs84GST9g5kul9MLCmxgIZ/l+wPLLEjrlKN
-                BvbH08MRVRqQVEk7PVTpJ2mKKikJkl0kZZLdytOHysDp4bQ0yeYzvQlNGpIm
-                5ac/JCQttpzSkmK39OyhvNynKaSTo6JIoROZGZlTpKvTitY1FBtgk2zp2SOZ
-                AtOhxyNGeob0bqGvZVvwCtEZiilxLSG4TjNxgsH/HdgkFukutieL3ooKP1hw
-                ncBzbdv0ru/SZYmFzespW45Zaextmd6nor6irG6V2xvcs8Q+Mg6vNZzA2jMN
-                58DyLTLNtXvDkFkPeHV3he9H3vlO73vc43smUftPWLpN0aStuu42vKq5aAmI
-                wQhi40w6GiaJ3jJRgl7xfpGmkE6vAq3LtFuk7xJJtXSCVGn4V2R+pp2Ej2nt
-                huj4CMWPIkWyTLvLoTd96xGzQZpApVGCRv8QUxcjQzJe+gWZoxZcomkcbcKk
-                Q4cIJkvkngePdQazlwbQy0KwImCKWApOqSeQ7g+f4MrjVlBINtUim4rIrkRs
-                LgFaCgMYjHKPR8XK5mLffAtFMJgtDR9jOISs0CqDCQS621H62yQFtdwTjN4/
-                wau9rx9jXEQeo6gVj3H1GNcfdxwjFzF6gQeteqsG41ENmgx+w43OMihRPMNN
-                vB3x+IKkaFe+NPET4rGjiT8hfYe4fDRxCmlFAF2l//fCEgt7Umm2T04qfyOb
-                pH27YvlWxfK4hXcpzyrpSUHqnWYN7jVD6XrhIyxR+T5pAhpYI/kZ2W9Tp2Y2
-                IRuYNXDHwF28RyreNzCH+U0wHwv4YBM9vvh96ENtrgkfmo+sj14ffT5uNo23
-                fOg+cqT/CwA97z/6BwAA
-                """,
-        """
-                androidx/navigation/Outer$InnerObject.class:
-                H4sIAAAAAAAA/41US08TURT+7p0+plMe5SFvnxR5KVMQVxATJBqHlGKEYJTV
-                bTvCwDCjM7cNS1bu3Lpw6cIVC4kLEk0MStz4o4jnTkdBCMakvec7Z84535nv
-                3Pbn8eevAKZxl2FIeNXAd6o7pifqzrqQju+ZSzVpB3nL8+xgqbxpV2QajCG3
-                KerCdIW3bv6OagypWcdz5D0GbWR0tQlJpAwkkGZIyA0nZBgu/hfDDIMu/WUZ
-                ON46Q+fIaPGErRGljMGiH6ybm7YsB8LxQlN4ni+jhqFZ8mWp5rqUlT3VVkcL
-                Nd4Q4ca8X7WjIS3tx/TxGxrcflUTLk14aaR49s1mRp8z5P/FRlSi7NpEl/Tl
-                hh0wtJ/vQtSzFTfSxwBXouhWaXllrjT/oAl9MDIU7GdoK275ktLMRVuKqpCC
-                Cvl2XaMdMXVk1AEGtkXxHUd5BULVSYYXh7tXDN7DDZ473DW4rkA2trqhQrkW
-                /ei10XO4O8UL7H5a59/fp3iOL3TktD5eSEzpuWRfoocV2KOjt9pCJpeiaJow
-                I6wTziis2KaYmqH3wm2mMUp3pCTq874nA9917WBiSzL0P6l50tm2La/uhA5p
-                NneiI92Sxl5ai45nl2rbZTtYUboqOf2KcFdF4Cg/DjYvS1HZWhQvYz9/tvdj
-                EYhtm6b5i6QpuhHzrghDm1xj2a8FFfuho1r0xi1Wzw2HSVpPIlK+V22L7C3y
-                UmSbySbpaTLybpNnqv2o6NgB9H0CHBNxMjBAj4GmRgIy1Eo1zVKER8XX42Kt
-                vfVj9OgkXYvTTzOTzGiLeU9K2/cuKGXoQGfMZJHlZLvHxj8gmdgb/wb+Dklt
-                b/wQ/GliLxq8QGcCPK1HzboaBXEzhbroy0gdqBtNvx8COnr+SNEdFQDZL+DP
-                DtD7CQP7UUDDFJ1KR44xtJCqdyK+cforUqMxXCZ5rqxBs3DVwjWL3u4GQQxa
-                yGNoDSzETQyvwQjVZyREKkRHBLpC5CKQpfMXu5HXfeAEAAA=
-                """,
-        """
-                androidx/navigation/Outer.class:
-                H4sIAAAAAAAA/4VRW2sTQRg9M5vLZhNtGi9NjK2XptpUcNviUy1CDQoLMYW2
-                BCRPk2SIk2xmYXcS+pgnf4j/oPhQUJCgb/4o8dttNA9S3GG/M9/tfDNnfv76
-                8g3ACzxjqAjdDwPVP3e1mKqBMCrQ7vHEyDALxlAciqlwfaEH7nF3KHsmC4sh
-                c6i0Mq8YrO16u4A0Mg5SyDKkzAcVMVSb17K+ZLAPe37S74DHTbbXOj07ajXe
-                FHADTo6CNxk2m0E4cIfSdEOhdOQKrQOT8ERuKzCtie8T1WpzFBgic99JI/rC
-                CIrx8dSi27HY5GIDBjai+LmKvV3a9fcY6vNZweFl7vDifOZw27J/fOTl+Wyf
-                77IDbqVeZ23+/VOGF3ncsM9iGsfTWoYNX0R0yXziXKnCULv2xrVlUxYPGLb+
-                U/lH50ekfktMG4E2YeD7Mnw+ojnVk4k2aiw9PVWR6vryaCkM6d8I+pJhpam0
-                bE3GXRmeCaphKDWDnvDbIlSxvwgWlieT1OycBpOwJ9+qOFdZzGn/MwV79EKp
-                RNZK/GCENfIyhEVCTiudeFvkubH4hOmdS9gXSfrJohio4inZwlUBckQF2Mj/
-                bV6j6vjLfwV/f4nCZ6xcJAEL22RLlH5I/zqd4zHhBmE9GbGJHcIDolkl4lIH
-                lodbHm57uIO7tMWahzIqHbAI91DtIB3BiXA/QibCeoSN33FlSFUiAwAA
-                """,
-        """
-                androidx/navigation/OuterComp$InnerClassComp$Companion.class:
-                H4sIAAAAAAAA/51TTW/TQBB9a6d2YkJJUz4SoHwGSBHUTQUIqQgJgpAipa0E
-                KJce0CZZyib2Gq3XUY858UP4Bz0hcUBRj/woxKwTqLgglcvMm3nzZr0z3h8/
-                v30H8AhNhidcDXUih4eh4hN5wI1MVLiXGaHbSfyp0VGKUMTTNA+t4YpKfDCG
-                yohPeBhxdRDu9UdiYHy4DN4zqaR5zuA213tlLMELUIDPUDAfZcrwtPt/R24z
-                tJrdcWIiqcLRJA6lIoniUfhKfOBZZNqJSo3OBibRO1yPhd5e7wVw7NGrjcEJ
-                +T7OWYaN03VjWPkt2BGGD7nhlHPiiUvDZNaUrAEDG1P+UNpok9CwxdCYTYPA
-                qTmBUyE0mxaPP7u12XTL2WQv/aJz/MVzKo6t3WK2w4PTzMjHFYa1fyp8rDEs
-                /y1jKP0ZLi1zl0/ozkYnUST0xtjQwtrJUDCc60oldrO4L/Q73o8oU+0mAx71
-                uJY2XiTLJ90FrTl4m2R6IF5Ly9XfZMrIWPRkKqn4hVKJyb8wRYs2VLBjI+/Y
-                v4Vuf4ui0M6R/NL9ryge5fRtsl6efIwG2fK8ACUEQIUROrMQPyTvLMTlo3wn
-                VnBxnpwLcnQWy8S5uENRldiruIbrqOfoBvm7+cE3cS9/LzQL0lT24Xaw0kG1
-                g1WcJ4gLHep9aR8sRQ114lMEKS6n8H4BDr3L2mwDAAA=
-                """,
-        """
-                androidx/navigation/OuterComp$InnerClassComp.class:
-                H4sIAAAAAAAA/5VUW0/cVhD+jvfmNQt4IRcCmyYt23S5BHNLSoE0XFKK6QIp
-                pDSE9uGw64LB2NT2ovSlylN+QqT2pVIf+sRDorZQFamiyVt/U1V1jm2WW4S0
-                0u45M+OZb74zM+f889+ffwEYxNcM3dwuu45ZfqrZfMdc477p2Np8xTfcSWdr
-                O6/bNkkW9zyhpsAY1A2+wzWL22va/OqGUfJTiDEkR03b9D9miBf0jiWGWKFj
-                KYMEUgrikBlkUyCNu2sMTM9AQV0aEjLk76+bHkNPsRYiIwx1a4avVzEpnc6g
-                lOibYxu230fAJWf7O4Y+4lMrdnvRcde0DcNfdblpexq3bccPojxtzvHnKpY1
-                Ig6XVOgMVxgyIlW+bHzDK5bP4BZqS6jrxbM1HamRcwbNuCTYtFKpfWfRd02b
-                ynKp0HECOrTS+a6etU1UTKtsuCm8o+CGaFfLafzCUffuyXiXms23tw27zHC7
-                cB7+fMYInUi2Iy8SvM+QE225yPED4VgQjpMXO3YKx64McrgupNtUgHXurU86
-                ZYMhexyp276xJs7YGw4pTaGGfgV9GKATGd9WuEVzeLnwll48YchfNBI0D3zV
-                MqiyCcdfN1yGpvMoxGu0ZEW35G4t3c2LhdvkksKImOjipuMTkraxs6WZdCzX
-                5pb2IBy/SWLku5WS77iz3N2kIoUX8Z6CUVDmdBWMYaimITumQXUfw7i4wBNU
-                4iM2s4bPy9znRFHa2onRC8PEkhYL6Npvkv2pKTTqgFSmK7p7+OymIrVIiqQe
-                PlPoJ6myIslJ2utoj9HeQGb59XO5hVwb+6VeNswaJ+qbkqrUKvXGXv+clNT4
-                TFpNCW36zfPYTLMqk3z4rF+WpdCJzIzMaZKVflmta423sF42/eZFjAIzoccL
-                RnI9yQ1CXshW4WXK3xqXE2pScO5n4iTXL6xaCg8ZGk6Xjl7NOb5DrfFdx7IM
-                t2eTnom2hYrtm1uGbu+YnknzM348UzSi4QA3Fk3bmKtsrRruIzFjYrScEreW
-                uGsKPTLWL/q8tDnLtyM9fxb7IXf5lkEUTyXJHNM0SFUWnYpbMqZMAXEtglg6
-                R46ujESvOmi9JgaBSvKItCTtl2lvEq+7aDzpicD6BWlT5C3RrnTuI93Z9jvq
-                XwUIS7Q2QEzFAGEOUtQAviTtSuhN3xrF/JAkUGncoNI/xNTEWNGe6PwN9btV
-                uGRgHAxgMqFDBJMlckfB7WeD2VsD6F0lWBHQRywFp/QBpOW2fVx9WQ0Kyaar
-                ZNMR2RNlUdNooXKFuW9FBczm4t//AFkwGO1s20NbCPmY1hiYQKBXLUo/TLug
-                ljvAjeV93Gx6bw+3ROQeOtSOPXTvoeflmWPkIkYn28OobNkqj7AGAYM/MHi2
-                DHIUz3AHdyMeX9Eu2pXv7PoFifhu19+QfkQittt1CGlWAHXT/ydhiYc9eRy0
-                L5aS/0U2RfpxxfLViuUxhI8ozzLJKUHqwyD9MFIR1ZYgKRE7wOgy28f9XzH5
-                KrDE8CSYOjFfn2OBijxK0hjtK0H6RaIMkhkeUF8/WUFMx5SOT3VMQycRMzo+
-                Q5EcPMxibgWqh0YP8x6UYE16wpL10OSh2cOdwDjkQfOQC+Sx/wHugknKUQkA
-                AA==
-                """,
-        """
-                androidx/navigation/OuterComp$InnerObject.class:
-                H4sIAAAAAAAA/41US08TURT+7p0+plMe5SFPxQeolCpTUFcQE2w0DinFCMEo
-                q0s7wsB0BmduG5as/AkuXLrQDQuJCxJNTJWdP8p47jAKQiQm7T2POef7znzn
-                tj9+fv4K4C7uMeSFVwt8p7ZjeqLprAvp+J652JB2UPLr22OW59nB4tqmXZVp
-                MIbcpmgK0xXeuvk7qzGkZh3PkfcZtPH8ShuSSBlIIM2QkBtOyFAo/zfLDIMu
-                /SUZON46Q+94vnzMeJSlitGyH6ybm7ZcC4TjhabwPF9GoKFZ8WWl4bpUlT0B
-                q6ODgDdEuFHya3Y0qKV5H4qzNLz9qiFcmvLCePn0283kXzCMncdGVGLNtYku
-                6csNO2DoPotC1LNVN9LIAFfC6FZlaXmuUnrYhiEYGUoOM3SVt3xJZeaCLUVN
-                SEGNvN7UaFdMHRl1gIFtUX7HUVGRvNoUw8vW7ojBB7jBc61dg+vKycZWN1Qq
-                16EfvjYGWrvTvMgepHX+/V2K5/h8T04b4sXEtJ5LDiUGWJE9PnyjzWdyKcqm
-                yWfk6+RnlK/Yppma4dK5G00jT3elIpol35OB77p2MLklGYafNjzp1G3Lazqh
-                Q7rNHWtJt+VoN51lx7MrjfqaHSwrbZWkflW4KyJwVBwn25ekqG4tiO04HjuN
-                /UQEom7TRH+RtEW3ouSKMLQpNJb8RlC1HzkKYjCGWDkzHKZoRYlI/UG1MbK3
-                KEqRbSebpKfJKLpNkal2pLITB9D3yeGYjItBQCadbUcFyBCUAs1ShkfNV+Nm
-                rbvzY/TouFyLy08yk8zoinmPW7v3/tHK0IPemMkiy8n2TxTeI5nYK3wDf4uk
-                tldogT9L7EWDF+lMgKf1CKzvqCEGU14ffRm9FNStpt8QOToG/kjRHzUA2S/g
-                zw8w+AkX96OEhmk6lY4cE+ggVe9EfAX6W1Kj0Q0jeUZWoVm4bOGKRW93jVyM
-                WhjD9VWwEDdwcxVGqD7jIVIheiKnL0QucrJ0/gKE9w8Q7AQAAA==
-                """,
-        """
-                androidx/navigation/OuterComp.class:
-                H4sIAAAAAAAA/41RW2sTQRT+ZjaXzWZt03hpYk2rtmpTxW2LT7UINSgsxC20
-                JSB5miRLnGQzK7uT0Mc8+UP8B8WHgoIEffNHiWe30SJCcYc935zbd+ac8+Pn
-                568AnuExQ02oXhTK3qmjxET2hZahcg7H2o8a4eh9HoyhNBAT4QRC9Z3DzsDv
-                6jwMhty+VFK/YDA26y0bWeQsZJBnyOh3MmZYa17J/JzB3O8GKYcFniSarnd8
-                cuA1Xtm4BqtAxgWG9WYY9Z2BrzuRkCp2hFKhTrlixwu1Nw4ColpqDkNNZM4b
-                X4ue0IJsfDQxqEuWiEIiwMCGZD+VibZNt94OQ302tS1e4RYvzaYWNw3z+wde
-                mU13+Tbb40bmZd7k3z7meIknCbssoVlwlaI2AhHHSS8MxdRwMR2GJ1d2vvF3
-                ch5r9Ij/yPg9+3u0EU9MGqHSURgEfvR0SDVXjsZKy5HvqomMZSfwDy4HRTtp
-                hD2fYbEple+NRx0/OhEUw1Buhl0RtEQkE31utC9f6FOydRyOo67/Wia+6rxO
-                658q2KGNZdIxV5MFEm6QliMsEXI62VR7QJqTLIMwu3UO8yx1P5wH02rwiKR9
-                EYACUQEmin+Slyk6+YpfwN+ew/6ExbPUYGCTZJncd+mv0TvuE64S1tMS69gi
-                3COaJSIut2G4uO7ihoubuEVXLLuooNoGi3EbK21kY1gx7sTIxajFWP0Fraxj
-                CzoDAAA=
-                """,
-        """
-                androidx/navigation/TestAbstract.class:
-                H4sIAAAAAAAA/4VRy0oDMRQ9SduxjlWnPusL1IWvhaPiThFUEApVQaUbV2kn
-                aOw0gUlaXPZb/ANXggspLv0o8WZ07+ZwHjfh5Obr+/0DwCFWGFaFTjKjkudY
-                i756EE4ZHd9J605b1mWi7UbAGKIn0RdxKvRDfN16kt4tMATHSit3wlDY2m5W
-                UEIQoogRhqJ7VJZhvfHf5UcM1UbHuFTp+FI6kQgnyOPdfoEKMg+jHsDAOuQ/
-                K6/2iCX71H04CENe4yGPiA0H5Y3acHDA99hZ6fMl4BH3cwfMn46uRP/caJeZ
-                NJXZbsdRyXOTSIbJhtLyqtdtyexOtFJyphqmLdKmyJTXf2Z4a3pZW14oLxZu
-                etqprmwqqyg91dq4/HG2uAZOO/ir7FdCWCMV5xoo7byh/EqEY4EwyM1NLBJW
-                fgcwijDPl3Kcx3L+VwxjlFXuUahjvI6JOiYREUW1jilM34NZzGCWcovQYs4i
-                +AEAejLS6AEAAA==
-                """,
-        """
-                androidx/navigation/TestAbstractComp$Companion.class:
-                H4sIAAAAAAAA/5VSy24TMRQ99qR5DAHSlkfCuyVILRKdpGJFEVIJQoqUFolW
-                2XSBnIkpTmY8yHaiLrPiQ/iDrpBYoKhLPgpxPQmwpZv7Ovfcax/756/vPwA8
-                xxOGHaGHJlPDs0iLqToVTmU6OpbW7Q+sMyJ2nSz93PRGaIJKYAy1kZiKKBH6
-                NHo3GMnYlRAwFF8qrdwrhmBru1/FCoohCigxFNwnZRlavcut2mNob/XGmUuU
-                jkbTNFLaSaNFEr2RH8UkoXZNvEnsMnMgzFiave1+CO5Xrjfjf+CHNEfprpeb
-                xrD6h3AgnRgKJ6jG02lA4jFvKt6AgY2pfqZ81qJo2GZozmdhyOs85DWK5rPy
-                xZegPp/t8hZ7XSrzi69FXuO+d5f5Cc3/0aaEuwyVvwLRQxyKKZ3bmSxJpNkZ
-                OxK7kw0lw/We0vJwkg6kORaDhCprvSwWSV8Y5fNlsdrVWppOIqyV9EThUTYx
-                sXyrPNZ4P9FOpbKvrKLmfa0zl5/Lok0qF/zVyXP/0nSDh5RFXgvyK0+/oXye
-                w4/IFvPiC2yQrS4aUEEI1BhFV5bkZ+T5klw9z3X1hFuL4oKQR1dxjbAAm5SF
-                Oeke7qOBx/nCB2jmf5s0oN7aCYIuVrtY62IdNyjEzS7NvH0CZlFHg3CL0OKO
-                RfE3/dAjtxgDAAA=
-                """,
-        """
-                androidx/navigation/TestAbstractComp.class:
-                H4sIAAAAAAAA/41RW2sTQRg9s5vrurFJvSXWS2trTPvQbYsgNEWoESGQpqAl
-                IHmaJGOdZDMrM5PQx/4W/0HxoaAgwUd/lPjtNrYPvuTlO/Ndzvku8/vP958A
-                XmKLYYOrgY7k4CxQfCpPuZWRCk6EsYc9YzXv20Y0/pIFYygO+ZQHIVenwXFv
-                KPo2C5chcyCVtK8Z3Npmx0caGQ8pZBlS9rM0DNXWIg3qDLmDfjiX2l6EshEb
-                riiVhc+wW2uNIksKwXA6DqSyQiseBm/FJz4JiaCIOenbSB9xPRK6fjXsbQ8F
-                LDHkr8UYdhaa+KZ93UcJy3k4uMOw3or0aTAUtqe5VCbgSkU2UTBBO7LtSRjS
-                rqV/sx4Jywfccoo546lLn8Jik48NGNiI4mcy9nboNdile87Ofc8pO55TnJ17
-                Ts7JVcuz81V3z9lh+8x9k/71NeMUnbh6j8UaxTaf0vpWR2Eo9PbIMqy8nygr
-                x6KpptLIXigOb6akj2tEA8Gw1JJKtCfjntAnnGoYlltRn4cdrmXsz4N+Uymh
-                GyE3RhDZ+xBNdF+8k3GuMu/T+a9Lao3OlUp2rMTXI1wnL0N4j9AhTCfeBnlB
-                fAnC9NYlchdJ+vm8GNhHlax/VYA8PMIcbl2Ty0huCf8HCh/ZJYrfcPciibh4
-                QdajugIplmiQWqL9DJuEryh+nxQfdOE2UW6i0sRDrNATj5p4jCddMIOnWO0i
-                ZeAZrBlkDEp/AVeTkqlcAwAA
-                """,
-        """
-                androidx/navigation/TestClass.class:
-                H4sIAAAAAAAA/31Ry0oDMRQ9N7VTHauO7/reqgtHxZ0iaEEoVAWVblylnaCx
-                0wQmaXHZb/EPXAkupLj0o8Q7o2s3h/O4CecmX9/vHwCOsEHYkCbJrE6eYyMH
-                +kF6bU18p5yvp9K5CogQPcmBjFNpHuLr9pPq+ApKhOBEG+1PCaXtnVYVZQQh
-                xlAhjPlH7QhbzX9vPibMNrvWp9rEl8rLRHrJnugNSlyNcpjIAQTqsv+sc7XP
-                LDkgbI6GYShqIhQRs9GwNhoein06L3++BCIS+dQh5WejKzmoW+Mzm6Yq2+t6
-                7le3iSLMNLVRV/1eW2V3sp2yM9e0HZm2ZKZz/WeGt7afddSFzsXKTd943VMt
-                7TSnZ8ZYX+zlcADB6/8Vzl+DscYqLjRQ3n3D+CsTgRXGoDCXscpY/R3ABMIi
-                XytwGevFHxEmOaveo9TAVAPTDcwgYorZBuYwfw9yWMAi5w6hw5JD8AOsqUxn
-                4AEAAA==
-                """,
-        """
-                androidx/navigation/TestClassComp$Companion.class:
-                H4sIAAAAAAAA/5VSy24TMRQ99qR5DAHSlkfCuxCkFminqdgVIUEQUqS0SKXK
-                pgvkJKY4mbGR7URdZsWH8AddIbFAUZd8FOJ6UmCJurmPc++5987x/Pz1/QeA
-                53jM8FTooTVqeJJoMVXHwiujk0PpfDsVzrVN9rkZjNCEl8AYaiMxFUkq9HHy
-                rj+SA19CxFB8obTyLxmi9Y1eFUsoxiigxFDwn5Rj2OxeYM8uQ2u9OzY+VToZ
-                TbNEaS+tFmnyRn4Uk9S3jXbeTgbe2D1hx9LubvRi8LBvtTn4V/yQ5VWGrYtN
-                Y1j+Q9iTXgyFF4TxbBqRbCyYSjBgYGPCT1TItikathia81kc8zqPeY2i+ax8
-                9iWqz2c7fJu9LpX52dcir/HQu8PChLX/ClPCbYbKX3XoCfbFlI721qSptFtj
-                TzK3zVAyXO0qLfcnWV/aQ9FPCVnpmoFIe8KqkJ+D1Y7W0uYLJD1O/N5M7EC+
-                VaHWOJhorzLZU05R8yutjc+PcmiRxIXw3eR5eGM6/z5lSRCC/NKTbyif5uUH
-                ZIs5+AxrZKuLBlQQAzVG0aVz8iZ5fk6unuaiBsKNBbgg5NFlXKFahIeUxTnp
-                Du6igUf5wnto5r80aUC9tSNEHSx3sNLBKq5RiOsdmnnzCMyhjgbVHWKHWw7F
-                3/peHcMPAwAA
-                """,
-        """
-                androidx/navigation/TestClassComp.class:
-                H4sIAAAAAAAA/4VRXWsTQRQ9s5vPdWOT+pVYP1obta0f2xRBsEXQiBBII2gp
-                SJ8myVgn2czIzCT0sb/Ff1B8KChI8NEfJd7dxvbBh7zcM/fMuWfuvfP7z/ef
-                AJ5hg2GFq77Rsn8UKT6Rh9xJraI9YV0z5tY29ehLHoyhPOATHsVcHUbvugPR
-                c3n4DLkdqaR7yeCvre+HyCIXIIM8Q8Z9lpZhtT3XfZuhsNOLZz6P5urrSeCK
-                +DxChsZae6gdlUeDySiSygmjeBy9EZ/4OHZNrawz457TZpeboTDbZ21eDlDC
-                AkPx3IzhyfxeL97eDlHBYhEeriRTanMYDYTrGi6VjbhS2qXlNupo1xnHMU1Z
-                +dfornC8zx0nzhtNfPoIloRiEsDAhsQfySTbpFO/wVCfHoeBV/UCrzw9DryC
-                V50eL/tb3iZ7wfzX2V9fc17ZS7RbLHEod/iEJndGx7EwT4eOYen9WDk5Ei01
-                kVZ2Y/Hqokf6rabuC4aFtlSiMx51hdnjpGFYbOsej/e5kUk+I8OWUsKkSxFU
-                HHzQY9MTb2VyV5u9s//fK2jQsjLphLVkd4SrlOUIrxF6hNk0q1MWJXsgzG6c
-                onCSXt+fiYHHeEAxPBOgiICwgEvnxVWkm0T4A6WP7BTlb7h6kjI+HlIMSFci
-                xwo1spZ638M64XPir5PjjQP4LVRbqLVwE0t0xK0WbuPOAZjFXSwfIGMRWKxY
-                5CwqfwEoeIqnTgMAAA==
-                """,
-        """
-                androidx/navigation/TestClassWithArg.class:
-                H4sIAAAAAAAA/41QTW/TQBScXSdOYhLihK805ZsKtTngtOIGqgiRkCyFIpUq
-                HHLaxJa7jbOWvJuox/wWzlyQQEgcUMSRH4V461ScOCDZ897sjuf5za/f338A
-                eI49hj2hojyT0WWgxEomwshMBWexNsNUaP1BmvNBnlTAGPwLsRJBKlQSvJte
-                xDNTgcPgvpRKmmOG0n54MGZw9g/GdZRR8VBClbjIEwYW1uHhWg0cdZKac6kZ
-                no7+Z/YLmpHEZmBtyDxkaI3mmUmlCt7GRkTCCJLwxcqhlZiFmgXQ0DmdX0rL
-                +tRFhwzDzbrt8Q73uL9Ze/Rwv+rxqtPZrI94n71utF2fd3nf+fnR5X7ptPWX
-                VUndLVXLvmutjpgd4J+I1TBTJs/SNM6fzQ2tNsyimKE5kio+WS6mcX4mpimd
-                tEfZTKRjkUvLrw6999kyn8VvpCU7p0tl5CIeSy3pdqBUZopINA4pt1KxU9vG
-                SB2nvgyX8AGxY+Kcqtf7hlpv9ysanwvNQ0KrAXbwiPD2VoXraNqIqLNulCh8
-                erdegU2Oarn3BY1P/7SpbwVXNhyPC7yPJ1RfFT9Zxo0JnBA3Q9wKaewdatEJ
-                6fvuBExjF3cnqGg0Ne5peAW6Gr5G6w+psmgInQIAAA==
-                """,
-        """
-                androidx/navigation/TestClassWithArgComp$Companion.class:
-                H4sIAAAAAAAA/5VSS29SQRT+Zi6FckWlrQ/wVR+YUBO5hXRXY1IxJiS0Jtrg
-                ogszwEgH7p0xcwfSJSt/iP+gKxMXhnTpjzKeuaBu7ea8vvOdM/PN/Pz1/QeA
-                PTxlaAk9tEYNzyItZmoknDI6Opapa8ciTT8od3pgR22TfK55IzTBBTCG8ljM
-                RBQLPYre9sdy4AoIGPIvlFbuJUNQ3+mVsIZ8iBwKDDl3qlKGve7l1+0zNOvd
-                iXGx0tF4lkRKO2m1iKPX8pOYxq5tdOrsdOCMPRR2Iu3+Ti8E92u3aoN/4Mck
-                Qxkal5vGsPGHcCidGAonqMaTWUAiMm+K3oCBTah+pny2S9GwyVBbzMOQV3jI
-                yxQt5usXX4LKYt7iu+xVYZ1ffM3zMve9LeYn1P9XnwLuMhT/ikQPciRmdHZn
-                TRxL25g4Er1thpLheldpeTRN+tIei35Mlc2uGYi4J6zy+apY6mgtbbZH0lOF
-                783UDuQb5bHqu6l2KpE9lSpqPtDauOxsKZqkdM5fnzz3L0632KYs8nqQX3v2
-                DevnGfyQbD4rNvCIbGnZgCJCoMwourIiPyfPV+TSeaatJ9xaFpeELLqKa4QF
-                eExZmJHu4T6qeJItfIBa9s9JA+otnyDoYKODzQ62cINC3OzQzNsnYCkqqBKe
-                IkxxJ0X+N9Gij4okAwAA
-                """,
-        """
-                androidx/navigation/TestClassWithArgComp.class:
-                H4sIAAAAAAAA/41S308TQRD+9vrrehY5KmIBf6CglqpcITwJIcEa4yWlJkhq
-                DE/bdi3bXvfM3rbhkb/FZ1+IGhJNDPHRP8o4d634oA8kdzM7szPfzHyzP399
-                /Q5gE+sMZa46OpSdY0/xkexyI0PlHYjI1AIeRW+kOdrV3Vo4eJ8DY3B7fMS9
-                gKuu96rVE22TQ4ohuy2VNDsM6bK/2mRIlVebBWSQc5CGTTbXXQbmF+DgSh4W
-                ChRqjmTEUKlftv4W1ekKsxtDUQGfwd5uB5PCG5dFWYkFV3SdwzWG9XK9HxpC
-                8XqjgSeVEVrxwHsu3vFhYGqhiowetk2o97juC701nuu6g1nMMeQvwBg2Lz3I
-                3xa2CihhPiZkgWG5Huqu1xOmpblUkceVCk2CEnmN0DSGQUAUzPzpd08Y3uGG
-                k88ajFK0ThaLfCxAZPfJfyxjq0qnDm365flJ0bFKlmO55ycOfZZrO5adLp2f
-                LOU2rCp7ynLPpopZ11qwqqkfH7KWm96fubBsSllI2xk3G+NtsLiK2+AjIsno
-                MAiEXusbhsX9oTJyIHw1kpFsBWL37xy09VrYEQzTdalEYzhoCX3AKYahWA/b
-                PGhyLWN74iz4Sgmd8Cco2XkdDnVbvJDx3fykTvOfKlgnQtM0uIX5mF/qs0JW
-                lvRN0sX4EZJOkZ1JvI/I2qFoi7RTOUO+svgFU6cJwuNJJrCGJyTnxlG4iumY
-                aDrFaLQXuPSPsbyYf9KZymdMffwvTGEcMIGxqancJLmEZIMofMPsW3aGG5+w
-                eJp4UpQbF2T0+KxkMC/BXkWVdI38twjx9iFSPu74WPJxF/foiGUfK7h/CBbh
-                AR4ewo4wHaEcwUlkNoIbYSZC6Tedt709GAQAAA==
-                """,
-        """
-                androidx/navigation/TestGraph.class:
-                H4sIAAAAAAAA/31SQWsTQRT+ZpJsNttoY6s2sdaq7UE9uG3xZhFqUFmIK9gQ
-                kJ4m2SGdZDMju5PQY07+EP9B8VBQKKHe/FHimzXoQXAW3nvfN998zHuzP35+
-                vQTwDLsMW0InmVHJWajFTA2FVUaHXZnbN5n4eFoFY2iMxEyEqdDD8F1/JAe2
-                ihKDd6i0si8YSo8e9+qowAtQRpWhbE9VzrDd+a/zcwb/cJAWHgG4O+hH8XH3
-                KG6/quMaghqR1xl2OiYbhiNp+5lQOg+F1sYWXnkYGxtP05SsbnTGxpJZ+FZa
-                kQgriOOTWYm6ZC7UXAADGxN/phzaoyrZZ9hdzIOAN3nAG1Qt5v73T7y5mB/w
-                Pfay6vOrzx5vcKc9YM6hEYtZ22ibmTSV2dOxZdh8P9VWTWSkZypX/VQe/b0j
-                jaNtEsmw2lFaxtNJX2ZdQRqGtY4ZiLQnMuXwkgyOzTQbyNfKgdbSuPePLfZp
-                OuWipZYbFuV7hDx3QcqcvkqBtgmFrnHKlScX8M+L7ftLMbCOBxTrvwWokRXg
-                Y+XP4Q1Su7XyDfzDBepfsHpeEBwPi7iFneJfokcgg7UTlCKsR7gZ4RZuU4mN
-                CE20TsBy3MEm7ecIctzN4f0CEKx6togCAAA=
-                """,
-        """
-                androidx/navigation/TestInterface.class:
-                H4sIAAAAAAAA/4WOz0rDQBDGv9lo08Z/qVqoR/Fu2tKbJykIgaqg4iWnbbIt
-                22x3IbsNPfa5PEjPPpR0Ux/AGfjmmxn4zfz8fn0DGKNHuOW6qIwsNonmtVxw
-                J41OPoR1qXaimvNchCBCvOQ1TxTXi+R1thS5CxEQutPSOCV18iwcL7jjDwS2
-                qgMPp0Y6jYBApZ9vZNMNvCuGhN5u245Yn0Us9m7e321HbEDNckS4m/77lb/k
-                wfELrydGu8ooJar70hGid7OucvEklSDcvK21kyvxKa2cKfGotXEHmG35UzjC
-                XzBcHfQS174OPfjYZytDkCJM0U7RQeQtTlKc4iwDWZzjIgOziC26e5qGvyhR
-                AQAA
-                """,
-        """
-                androidx/navigation/TestObject.class:
-                H4sIAAAAAAAA/32Sz2sTQRTHvzNJNptttLH+aGK1VtuDenDb4s0i1KCwEFew
-                IVB6mmSHOMlmBnYnS485+Yf4HxQPBQUJevOPEt+sUQ+Cu/De+37nzYeZt/v9
-                x6cvAJ5ij2Fb6CQzKjkPtSjUWFhldNiXuX0znMiRrYMxtCaiEGEq9Dj87VYY
-                vCOllX3OUHn4aNBEDV6AKuoMVftO5Qw7vf+jnzH4R6O0hATgbqcfxSf947j7
-                sokrCBpkXmXY7ZlsHE6kHWZC6TwUWhtbwvIwNjaepymhrvWmxhIsfC2tSIQV
-                5PFZUaF7MhcaLoCBTck/V07tU5UcMOwtF0HA2zzgLaqWC//be95eLg75PntR
-                9/nXDx5vcdd7yByhFYuia7TNTJrK7MnUMmy9nWurZjLShcrVMJXHf89I8+ia
-                RDKs95SW8Xw2lFlfUA/DRs+MRDoQmXJ6ZQYnZp6N5CvlRGcFHvyDxQFNp1pe
-                qeOGRXmblOcOSJnTWyvVPVKhuzjl2uNL+Bfl8s6qGbiJ+xSbvxrQIBTgY+3P
-                5k3qds/aZ/DTSzQ/Yv2iNDgelPEudsu/iT4CATbOUIlwPcKNiNC3qMRmhDY6
-                Z2A5bmOL1nMEOe7k8H4CjO1ti4oCAAA=
-                """
-    )
diff --git a/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongStartDestinationTypeDetectorTest.kt b/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongStartDestinationTypeDetectorTest.kt
index eaaf466..7b31a26 100644
--- a/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongStartDestinationTypeDetectorTest.kt
+++ b/navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/WrongStartDestinationTypeDetectorTest.kt
@@ -17,22 +17,15 @@
 package androidx.navigation.runtime.lint
 
 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest.compiled
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin
-import com.android.tools.lint.checks.infrastructure.TestFile
 import com.android.tools.lint.checks.infrastructure.TestMode
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
+import org.junit.runners.JUnit4
 
-@RunWith(Parameterized::class)
-class WrongStartDestinationTypeDetectorTest(private val testFile: TestFile) : LintDetectorTest() {
-
-    private companion object {
-        @JvmStatic @Parameterized.Parameters public fun data() = listOf(SOURCECODE, BYTECODE)
-    }
+@RunWith(JUnit4::class)
+class WrongStartDestinationTypeDetectorTest : LintDetectorTest() {
 
     @Test
     fun testEmptyConstructorNoError() {
@@ -42,7 +35,10 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.navigation.TestNavHost
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -56,7 +52,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .skipTestModes(TestMode.FULLY_QUALIFIED)
             .run()
@@ -71,7 +68,9 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -93,7 +92,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .run()
             .expectClean()
@@ -107,7 +107,9 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -124,7 +126,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .run()
             .expectClean()
@@ -138,7 +141,9 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.NavController
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navController = NavController()
@@ -160,84 +165,85 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .run()
             .expect(
                 """
-src/com/example/test.kt:7: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:9: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestClass(...)?
 If the class TestClass does not contain arguments,
 you can also pass in its KClass reference TestClass::class [WrongStartDestinationType]
     navController.createGraph(startDestination = TestClass) {}
                                                  ~~~~~~~~~
-src/com/example/test.kt:8: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:10: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestClassWithArg(...)?
 If the class TestClassWithArg does not contain arguments,
 you can also pass in its KClass reference TestClassWithArg::class [WrongStartDestinationType]
     navController.createGraph(startDestination = TestClassWithArg) {}
                                                  ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:9: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:11: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor InnerClass(...)?
 If the class InnerClass does not contain arguments,
 you can also pass in its KClass reference InnerClass::class [WrongStartDestinationType]
     navController.createGraph(startDestination = Outer.InnerClass) {}
                                                  ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:10: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:12: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor InterfaceChildClass(...)?
 If the class InterfaceChildClass does not contain arguments,
 you can also pass in its KClass reference InterfaceChildClass::class [WrongStartDestinationType]
     navController.createGraph(startDestination = InterfaceChildClass) {}
                                                  ~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:11: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:13: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor AbstractChildClass(...)?
 If the class AbstractChildClass does not contain arguments,
 you can also pass in its KClass reference AbstractChildClass::class [WrongStartDestinationType]
     navController.createGraph(startDestination = AbstractChildClass) {}
                                                  ~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:12: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:14: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestInterface(...)?
 If the class TestInterface does not contain arguments,
 you can also pass in its KClass reference TestInterface::class [WrongStartDestinationType]
     navController.createGraph(startDestination = TestInterface)
                                                  ~~~~~~~~~~~~~
-src/com/example/test.kt:13: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:15: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestAbstract(...)?
 If the class TestAbstract does not contain arguments,
 you can also pass in its KClass reference TestAbstract::class [WrongStartDestinationType]
     navController.createGraph(startDestination = TestAbstract)
                                                  ~~~~~~~~~~~~
-src/com/example/test.kt:15: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:17: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navController.createGraph(startDestination = TestClassComp)
                                                  ~~~~~~~~~~~~~
-src/com/example/test.kt:16: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:18: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navController.createGraph(startDestination = TestClassWithArgComp)
                                                  ~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:17: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:19: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navController.createGraph(startDestination = OuterComp.InnerClassComp)
                                                  ~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:18: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:20: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navController.createGraph(startDestination = InterfaceChildClassComp)
                                                  ~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:19: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:21: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navController.createGraph(startDestination = AbstractChildClassComp)
                                                  ~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:20: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:22: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
@@ -256,7 +262,9 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.TestNavHost
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navHost = TestNavHost()
@@ -278,7 +286,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .run()
             .expectClean()
@@ -292,7 +301,9 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.TestNavHost
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navHost = TestNavHost()
@@ -310,7 +321,8 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .run()
             .expectClean()
@@ -324,7 +336,9 @@
                         """
                 package com.example
 
-                import androidx.navigation.*
+                import androidx.navigation.TestNavHost
+                import androidx.navigation.createGraph
+                import androidx.test.*
 
                 fun createGraph() {
                     val navHost = TestNavHost()
@@ -345,84 +359,85 @@
                 """
                     )
                     .indented(),
-                testFile,
+                *NAVIGATION_STUBS,
+                TEST_CODE
             )
             .run()
             .expect(
                 """
-src/com/example/test.kt:7: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:9: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestClass(...)?
 If the class TestClass does not contain arguments,
 you can also pass in its KClass reference TestClass::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = TestClass) {}
                                            ~~~~~~~~~
-src/com/example/test.kt:8: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:10: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestClassWithArg(...)?
 If the class TestClassWithArg does not contain arguments,
 you can also pass in its KClass reference TestClassWithArg::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = TestClassWithArg) {}
                                            ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:9: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:11: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor InnerClass(...)?
 If the class InnerClass does not contain arguments,
 you can also pass in its KClass reference InnerClass::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = Outer.InnerClass) {}
                                            ~~~~~~~~~~~~~~~~
-src/com/example/test.kt:10: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:12: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor InterfaceChildClass(...)?
 If the class InterfaceChildClass does not contain arguments,
 you can also pass in its KClass reference InterfaceChildClass::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = InterfaceChildClass) {}
                                            ~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:11: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:13: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor AbstractChildClass(...)?
 If the class AbstractChildClass does not contain arguments,
 you can also pass in its KClass reference AbstractChildClass::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = AbstractChildClass) {}
                                            ~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:12: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:14: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestInterface(...)?
 If the class TestInterface does not contain arguments,
 you can also pass in its KClass reference TestInterface::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = TestInterface)
                                            ~~~~~~~~~~~~~
-src/com/example/test.kt:13: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:15: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor TestAbstract(...)?
 If the class TestAbstract does not contain arguments,
 you can also pass in its KClass reference TestAbstract::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = TestAbstract)
                                            ~~~~~~~~~~~~
-src/com/example/test.kt:14: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:16: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = TestClassComp) {}
                                            ~~~~~~~~~~~~~
-src/com/example/test.kt:15: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:17: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = TestClassWithArgComp) {}
                                            ~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:16: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:18: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = OuterComp.InnerClassComp) {}
                                            ~~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:17: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:19: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = InterfaceChildClassComp) {}
                                            ~~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:18: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:20: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
     navHost.createGraph(startDestination = AbstractChildClassComp) {}
                                            ~~~~~~~~~~~~~~~~~~~~~~
-src/com/example/test.kt:19: Error: StartDestination should not be a simple class name reference.
+src/com/example/test.kt:21: Error: StartDestination should not be a simple class name reference.
 Did you mean to call its constructor Companion(...)?
 If the class Companion does not contain arguments,
 you can also pass in its KClass reference Companion::class [WrongStartDestinationType]
@@ -438,600 +453,3 @@
     override fun getIssues(): MutableList<Issue> =
         mutableListOf(WrongStartDestinationTypeDetector.WrongStartDestinationType)
 }
-
-private val SOURCECODE =
-    kotlin(
-            """
-package androidx.navigation
-
-import kotlin.reflect.KClass
-import kotlin.reflect.KType
-
-public open class NavDestination
-
-// NavGraph
-public open class NavGraph: NavDestination() {
-    public fun <T : Any> setStartDestination(startDestRoute: T) {}
-}
-
-// NavController
-public open class NavController
-
-public inline fun NavController.createGraph(
-    startDestination: Any,
-    route: KClass<*>? = null,
-): NavGraph { return NavGraph() }
-
-// NavHost
-public interface NavHost
-public class TestNavHost: NavHost
-
-public inline fun NavHost.createGraph(
-    startDestination: Any,
-    route: KClass<*>? = null,
-): NavGraph { return NavGraph() }
-""" +
-                TEST_CLASS
-        )
-        .indented()
-
-// Stub
-private val BYTECODE =
-    compiled(
-        "libs/StartDestinationLint.jar",
-        SOURCECODE,
-        0x8e62b385,
-        """
-                META-INF/main.kotlin_module:
-                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgUucSTsxLKcrPTKnQy0ssy0xPLMnM
-                zxMS8Essc0ktLsnMA/O9S7hEubiT83P1UisScwtyUoXYQoCy3iVKDFoMAGXO
-                +shYAAAA
-                """,
-        """
-                androidx/navigation/AbstractChildClass.class:
-                H4sIAAAAAAAA/41QTW8SURQ9780wwBRkwC9K/ajVNpSF0MaN0TRSjAkJdtE2
-                LGD1YCb0hWEmmfcgXfJbXLsx0Zi4MMSlP8p431CNCxYu3rn33Hdy7sfPX9++
-                A3iBfYYDEflJLP3rZiQWciK0jKNme6R0Isa6cyVDvxMKpbJgDLubtJeB0n/0
-                WVgMzmsZSX3CYNcHh30Gq37YLyCDrAsbOeIimTCwQQEutvLgKJBUX0nFUO/9
-                3zSvqMsk0G1jRPYDhnJvGutQRs33gRa+0IIkfLawaE1mIG8A1HZK9WtpWIsy
-                /4jhdLWsuLzK07dautzbcnnOqq6Wx7zFTosVx+M13rJ+fHC4Z5+X/7IcqWt2
-                LuM5xumYYW/j+P8eiKaiIcpnYvGWqjJKFc+nmi7Qif2AodSTUXA2n42C5FKM
-                QqpUevFYhH2RSMNviu5FPE/GwTtpyPb5PNJyFvSlkvTbjqJYp8YKR3ReO128
-                Yq5NGac8A4dwl9gJcU7RbXxFvrHzBcVPqeYJodEAL7FHeG+twi2UzB0pM260
-                CTx6a6+mOS/FTOMzih832hTWghsbjqcpPsYzim/SITO4PYTVxZ0u7nap7X1K
-                Ue1iG7UhmMIOHgyRVSgpPFRwFR4pOAqeQvk3MHA2w9YCAAA=
-                """,
-        """
-                androidx/navigation/AbstractChildClassComp$Companion.class:
-                H4sIAAAAAAAA/51Sy24TMRQ99qR5DAHSlkfC+xGkthKdpqrYFCGVVEiR0iIB
-                yqYL5MyY1smMB42dqMuu+BD+oCskFijqko9CXDsBtsDm+t5z7rnXczzff3z9
-                BmAHTxh2hE6KXCWnkRZTdSysynW0NzS2ELHtnqg06abCmG6efWy7IDQ1VMAY
-                GiMxFVEq9HH0ejiSsa0gYCg/V1rZFwzB2vqgjiWUQ5RQYSjZE2UYnvX/Z+Eu
-                Q2etP85tqnQ0mmaR0lYWWqTRvvwgJqnt5pomTGKbFweiGMtid30QgrvFq+34
-                D/k+8yzD5r9NY1j+JTiQViTCCsJ4Ng3ISOZCzQUwsDHhp8pVW5QlHYb27CwM
-                eZOHvEHZ7Kx68Slozs62+RZ7Wanyi89l3uCud5u5CRt/71AFtxlqv22iWx6K
-                6b40Vmkv2xxbcr6bJ5Lhal9peTjJhrJ4J4YpISv9PBbpQBTK1Quw3tNaFn6D
-                pPcK3+aTIpavlONabybaqkwOlFHUvKd1bv0egw6ZXXIO0Mnds9OH3KcqcpbQ
-                ubTxBdVzTz+gWPZgHw8p1ucNqCEEGoyySwvxUzr5Qlw/9/Y6wY05OBf47DKu
-                EBfgEVWhF93BXbTw2C+8h7b/3ckD6m0cIehhuYeVHlZxjVJc79HMm0dgBk20
-                iDcIDW4ZlH8CofOnlCsDAAA=
-                """,
-        """
-                androidx/navigation/AbstractChildClassComp.class:
-                H4sIAAAAAAAA/5VSzU8TQRT/zW4/lyJtRSzgBwpiqcgWQjwIIcESTZPSA5Im
-                wmnarmXodtbsTBuO/C2evRA1JJoY4tE/yvhmWyFRDnqYefPe/N7vff74+eUb
-                gHWsMZS4bIeBaJ+4kg9Eh2sRSHe7qXTIW7pyJPx2xedKVYLeuyQYw8J1+H1P
-                6UufCGkzJDaFFHqLIVY8WGow2MWlRgZxJB3EkCKdhx0GdpCBg7E0LGQIqo+E
-                Yliu/XtWGxSp4+ltQ0YhDhhSmy1/FHr933kWzMUlAZK4ybBarHUDTTzu8aDn
-                Cqm9UHLf3fHe8r5PRUri6Ld0EO7ysOuFG8PabjmYxBRD+pKM4dl/FHOVxEYG
-                BUybtswwzNeCsOMee7oZciGVy6UMdMSj3Hqg633fpzbkfme862ne5pqTzeoN
-                bBo1M1faXKCWd8l+IoxWpld7leHVxWnesQpWdC5OHSs75lipWOHidC65ZpXZ
-                c5Z8MZ5PZK0Zq2x/f5+wsrG93KWWIpeZWCqeTRg6WqrFa0v+c0soPcomV+eD
-                HfoRMkKtdDXD7F5fatHzqnIglGj63vZVwbQklaDtMUzUhPTq/V7TC/c5YRjy
-                taDF/QYPhdFHxkxVSi+MOuyRs/M66Ict76Uwf9OjOI2/omCVOh+jDlmYNoOg
-                RJ+QliB5h2Te7CxJm/R4ZF0mbYvQFkmndI50afYzxs8ihqcjT6CGFbqnhijc
-                wISZCL0MG7UCWTpDLtcMimS89AnjH66lyQwBI5oUJZUcORcQjRqZr5h8w85x
-                +yNmzyKLTcQmIKM9taLCyhF3iQoGKmS/S4z3DmFXcb+KuSoe4CE9MV/FAh4d
-                giks4vEhUgoTCkUFR2FJIaGQVcgpFH4BxvFHnF0EAAA=
-                """,
-        """
-                androidx/navigation/AbstractChildObject.class:
-                H4sIAAAAAAAA/41Sy2oUQRQ9VfPq6Yzm4SMzxkdMhBgXdhJcaRDGUaGhbcEM
-                A5JV9YOkMj3V0F0zZDkrP8Q/CC4CCjLozo8Sb5XjA8zCbvreuueeOtX3UN++
-                f/wM4BHuMWwJlRS5TE49JSbySGiZK68blboQse4dyyx5HZ2ksW6AMaxfRO6n
-                pf61oYEKQ31fKqmfMlTubw9aqKHuoooGQ1Ufy5JhO/jPM58wOPtxZtVccCPh
-                +OFBvxv2XrRwCW6TwMsMm0FeHHknqY4KIVXpCaVybVVLL8x1OM4ykloOhrkm
-                Me9VqkUitCCMjyYVcoKZ0DQBDGxI+Kk01Q6tkl06YDZ1Xd7m9ptNna/veHs2
-                3eM77FnD4V/e1/kSN9Q9ho0Lh/vbI/MroZg8J0gq23441Axrb8ZKy1Hqq4ks
-                ZZSl3T9TkHW9PEkZFgOp0nA8itKiL4jDsBLkscgGopCmnoPuQT4u4vSlNEVn
-                Ljz4Rxa75F/VDt0xdlK+TVWd8hJlTm/NVneo8ow1lGsPzuGc2fb6nAw8xl2K
-                rZ8ENEkKcLDwe/Mqsc2z8An87TlaH7B4ZgGODRtvYdPeSPKGBFYOUfFxxcdV
-                H9dwnZZY9dFG5xCsxA2sUb+EW+JmifoP1gZuws4CAAA=
-                """,
-        """
-                androidx/navigation/AbstractChildObjectComp.class:
-                H4sIAAAAAAAA/5VSW2sTQRg9M0k2m220tV6aWO8t4gXdtvhmEWJUWNiu0IaA
-                9Gk2u7TTbGZldxL6mCd/iP+g+FBQkKBv/ijxmzFU0L64y36XM+c7s3OYHz8/
-                fwXwDOsMj4VKilwmx74SE3kgtMyV34lLXYiB7h7KLHkbH6VU5qP3dTCG9fMG
-                emmpz4Yss8LgbEsl9QuGyoOH/SZqcDxUUWeo6kNZMjwJ/2Pv5wzu9iCzih64
-                kXGDaK/Xibqvm7gAr0HgRYa1MC8O/KNUx4WQqvSFUrm2yqUf5ToaZxlJXQqH
-                uSYxfyfVIhFaEMZHkwq5wkxomAAGNiT8WJpug6pkkzaYTT2Pt7j9ZlP3+wfe
-                mk23+AZ7WXf5t48OX+KGusVw/9wD/u2V+Z1ITF4RLJWlPB1qhtXdsdJylAZq
-                IksZZ2nnz0nIwm6epAyLoVRpNB7FadETxGFYDvOByPqikKafg95ePi4G6Rtp
-                mvZcuP+PLDbJw6o9eNtYSvkWdQ7lJcqc3prtblPnG3so1x6dwj2xy3fmZGAH
-                dyk2fxPQICnAxcLZ8AqxzbPwBfzdKZqfsHhiAY57Nt7Emr2h5A0JLO+jEuBy
-                gCsBruIalVgJ0EJ7H6zEdazSegmvxI0Szi+zsivd3gIAAA==
-                """,
-        """
-                androidx/navigation/InterfaceChildClass.class:
-                H4sIAAAAAAAA/41Qz28SQRT+ZhZY2FJZqFZK/VWrtnBwaaMnTWNbY0KCbVIb
-                DnAaYKVTltlkZyA98rd49mKiMfFgiEf/KOMbSpqYcPAw773vvW++9+P3nx8/
-                AbzADsOOUP0klv2rQImJHAgjYxU0lAmTj6IXHl/IqH8cCa1dMAb/UkxEEAk1
-                CE67l2HPuHAYtpZJnIfa3Mi4SDNkXkslzQFDarddbTE4u9VWHi5yHlLwCItk
-                wMDaeeSxmgPHLaKaC6kZqs3/nPIVtRmE5tAqkX6bodgcxiaSKngfGtEXRhCF
-                jyYO7c+syVkD6juk/JW0qE5Rf4/haDYtebzM52829bi/4vGsU55N93mdHa2W
-                Mj6v8Lrz61OG+6mz4g3KEruSyqb9jFXaZ9heOv8/J6KxaIriiZi8pbRUc8rz
-                oaEbHMf9kKHQlCo8GY+6YXIuuhFlSs24J6KWSKTFi6T3IR4nvfCdtGDjbKyM
-                HIUtqSVVD5WKzVxYY48OnKKOGXole3FanFPsIkv2MaEDwpy8V/uOldrmNxS+
-                zDnbZO0v4CWekF2/ZsFH0Z6SIqtGu5Du2kIrsBcmn659ReHzUpn8NWEhw/F0
-                brfwjPwbqt2m2p0OnAbWG7jbQBkbFKLSwCbudcA07uNBB65GUeOhRl7jkUZW
-                o6Sx9hcxw6Dy8gIAAA==
-                """,
-        """
-                androidx/navigation/InterfaceChildClassComp$Companion.class:
-                H4sIAAAAAAAA/51STW/TQBB9u07zYQJNWz4SvgtBakHUTQXiUIQEqZAspUUC
-                lEsPaGNv203sNfJuoh5z4ofwD3pC4oCiHvlRiFknwLlcZmfemzezfuufv77/
-                APAMjxieCx3nmYpPAy0m6lhYlekg1FbmRyKS3ROVxN1EGNPN0s9tF4SmjgoY
-                Q2MoJiJIhD4O3g2GMrIVeAzll0or+4rB29js17GEso8SKgwle6IMw4vef23c
-                Zehs9EaZTZQOhpM0UE6hRRLsySMxTmw308bm48hm+b7IRzLf3ez74G7zWjv6
-                R35KC5Zh62LTGFb+CPalFbGwgjCeTjyykrlQcwEMbET4qXLVNmVxh6E9m/o+
-                b3KfNyibTavnX7zmbLrDt9mbSpWffy3zBne9O8xNeHIBiyq4xVD76xNd80BM
-                9qSxShe6rZEl77tZLBmWe0rLg3E6kPlHMUgIWe1lkUj6IleuXoD1UGuZFxsk
-                vZj/IRvnkXyrHNd6P9ZWpbKvjKLm11pntthj0CG3S84COrl7ePqSe1QFzhM6
-                lx5/Q/WsoO9TLBdgiHWK9XkDavCBBqPs0kL8lE6+ENfPCn+d4PocnAuK7DKu
-                EOfhAVV+IbqNO2jhYbHwLtrFH08eUG/jEF6IlRCrIdZwlVJcC2nmjUMwgyZa
-                xBv4BjcNyr8BSdfj0S4DAAA=
-                """,
-        """
-                androidx/navigation/InterfaceChildClassComp.class:
-                H4sIAAAAAAAA/5VSW08TURD+zrb0RpG2KJbiBQS1FGELYkyEkGCNZpNSEyRN
-                hKfT9lBOuz1rdk8bHvktPvtC1JBoYoiP/ijjnKXCgySGh52Zb3bmm8uZX7+/
-                /QCwhjWGRa5avidbR7biA9nmWnrKdpQW/gFvisqhdFsVlwdBxet9iIMxZDp8
-                wG2Xq7b9ttERTR1HhGH2KppdEegLqjhGGGIbUkm9yRAt7i3UGSLFhXoacSRT
-                iCJFmPttBraXRhpjSVi4QaH6UAYMS9VrdLpOpdpCbxk2qrHHkNhousPaz65B
-                NG8EVxQRxy2GlWK162kisjuDni1NjuKu/Uoc8L6rK54KtN9vas/f5n5X+Ovn
-                091OYRJ5huQFGcPz64xz2cV6GgVMm83cYZiren7b7gjd8LlUgc2V8nRIFNg1
-                T9f6rkuLyP5teVto3uKak8/qDSJ0AcyIpBGgrXfJfyQNKpPVWmF4c3acS1l5
-                K/zOjlNWZjRlJaL5s+OZ+KpVZi9Y/OVYLpaxClY58vNjzMpEd7IXKEEphWhi
-                JBMzdKum3/9eCfVGrWRrfPCK3FKFIctdzTC901da9oSjBjKQDVdsXU5LR1Lx
-                WoJhvCqVqPV7DeHvcophyFW9Jnfr3JcGD51pRynhh+sVlJx65/X9pngtzb+p
-                YZ36P1WwQmuPUnsx0lPmHcheonXFSN8jnTNXSzpCOI4EyWVCmxRtkU6VTjFa
-                mv6K8RNCFuxhJuCgTHLyPAoZZM2DkGXYaBnEOzHkss07kR4pfcH4pytp0ucB
-                Q5oEbiI5TM4jfGmkv2PyPTvF1GfcPQk9ERrNFGRhEwUabjXkfoKnpCvkv0+M
-                M/uIOJh18MDBHObJxEMHj/B4HyxAEQv7SATIBigFSAdYDAzMBZgIUPgDTG80
-                x3MEAAA=
-                """,
-        """
-                androidx/navigation/InterfaceChildObject.class:
-                H4sIAAAAAAAA/41SS2/TQBD+dpMmjmtoWl4J5VXaotIDbivEhQqpBJAsBSPR
-                KBLqaRMv6SbOWrI3Vo858UP4BxWHSiChCG78KMSsCeUAEtjaeXwz83lm1t++
-                f/wM4CHuMWwJHaWJik58LXI1EEYl2g+0kelb0ZetYxVHr3pD2TdVMIb6UOTC
-                j4Ue+L/QEsPa3zg6MjPnPFUsMFT2lVbmCUNp637XQxWOizJqDGVzrDKG7fb/
-                9vKYwdnvxwWdC245nCA87ByEreceluDVCKwzrLeTdOAPpemlQunMF1onpqDN
-                /DAx4SSOiWq5PUoMkfkvpRGRMIIwPs5LtCJmRc0KMLAR4SfKejtkRbv0gdnU
-                dXmDF2c2db6+443ZdI/vsKdVh395X+F1blP3bC//3JLtJRT5M8KULuIPRoZh
-                9fVEGzWWgc5VpnqxPPg9Bi2vlUSSYamttAwn455MO4JyGFbaSV/EXZEq689B
-                9zCZpH35QlmnOSfu/kGLXVpgmWau0GnajZK+Q4Nbf4U0p5cukLw18ny7HdIL
-                22dwT4vw3Xky8AjrJL2fCVgkC1R44bz4GmXbZ/ET+JszXPyA5dMC4Ngo5G1s
-                Fn8rwyUiuHyEUoArAa4GVNogE80A17F6BJbhBm5SPIOX4VYG5wfApo4N6gIA
-                AA==
-                """,
-        """
-                androidx/navigation/NavController.class:
-                H4sIAAAAAAAA/4VRu0oDQRQ9d2I2ukZNfMYXGGzUwlWxUwSNCIGooJLGapId
-                4pjNDOxOgmW+xT+wEiwkWPpR4t01vc3hPGbuHO58/3x8AjjGJqEqTRhbHb4E
-                Rg50RzptTXAjBzVrXGyjSMUFEKH0LAcyiKTpBLetZ9V2BeQI3qk22p0Rcju7
-                zSLy8HxMoECYcE86IWw3/p1+Qig3utZF2gTXyslQOsme6A1yXJFSmEoBBOqy
-                /6JTdcAsPCRsjYa+LyrCFyVmo+HkcmU0PBIHdJH/evVESaTnjii9XeZnL1Xi
-                tMla7Hcd16zZUBHmGtqom36vpeIH2YrYmW/YtoyaMtapHpv+ve3HbXWlU7F6
-                1zdO91RTJ5rTc2OsywYnqELwFsad06UwVlgFmQbye++YfGMisMroZeYs1hiL
-                fwcwBT/L1zNcwUb2XYRpzoqPyNUxU8dsHXMoMUW5jnksPIISLGKJ8wR+guUE
-                3i+86bUs6wEAAA==
-                """,
-        """
-                androidx/navigation/NavDestination.class:
-                H4sIAAAAAAAA/4VRO08CQRD+ZoEDTpSHiuAjUWOhFh4SO42Jj5iQICZqaKwW
-                7oLLYy/hFkLJb/EfWJlYGGLpjzLOnTRWNl++x+zMZPbr+/0DwAm2CLtSu0Nf
-                uRNHy7HqSKN87TTk+NoLjNKRTIIIua4cS6cvdce5a3W9tkkiRrDOlFbmnBDb
-                P2hmkIBlI44kIW6eVUDYq//f/pSQr/d801faufWMdKWR7InBOMZLUgjpEECg
-                HvsTFaoKM/eYsD2b2rYoCVvkmM2mqWJpNq2KCl0mPl8skRNhXZXC1/m/c496
-                hve88l2PkK0r7TVGg5Y3fJStPjuFut+W/aYcqlDPTfvBHw3b3o0KRfl+pI0a
-                eE0VKE4vtPZN1DjADgSfYb5zeBXGEisn0kDi8A2pVyYCZUYrMi2sM2Z+C5CG
-                HeUbEa5hM/owwgJnmSfEalisYamGLHJMka+hgOUnUIAVrHIewA5QDGD9AKYj
-                0APtAQAA
-                """,
-        """
-                androidx/navigation/NavDestinationKt.class:
-                H4sIAAAAAAAA/61WbVPbRhB+zsbYCGOECW8GDAGHGGgQEJI0hZJSaILKS1Kg
-                pJS26WGEEQgpo5OZdDrT5lP/Q7/2FyTlQzplppPJt/ZHdbqnCgw2BibDB5/2
-                9naffXZv787//PvnXwDGsMGQ4fam65ibLzSb75t57pmOrS3y/RlDeKbtT+e8
-                KBiDusP3uWZxO6893tgxcqQNM9TmXIN7xiOXP99msLLzFfCmHdtzHcsy3PH5
-                UqDx+V3Hs0xbc40ti+ba3LTFhRjvrwTmRxtncK4y3MTA5MURe+cdN6/tGN6G
-                y01baNy2Hc+3Etqi4y0WLIusMudZkQnfsAwyq57wtk0xGYPCkA447ezvaabt
-                Ga7NLU2nJMjfzIko4gxNuW0jtxuEecJdvmeQIcPN7Bk5FjXLEiQ/3r8aRwL1
-                Cuqg0m4Kj7veiV2OIcnQcV76UVyTnE3b9CYZwlkJ2IwWBU1oJcCMmdnKnOoG
-                pjM0ZGSOp/W9l9g1hmR5UgwR1yl4BkNLhZZhaDwRKrNpbPGC5TH8fKWNqZdb
-                Xtg5HWWFeFYYHTsmuFWR4KwjvCs8M+bVBLrUaek8NxTDD1eU9PvsR2Pe8Hxv
-                3aajYOeMJWOL4Xr2bMcVOihHHabmyty6LnCKYwCDNQjhA4ZUaeCnprc95eZ9
-                oOxF8QNjotGSqwTSdzmIOIYxIkmNMrQSKd22Dbe8JJUoPaaD6GaKTkSpyTwb
-                4mxCZQBx3MU9SehDhthEzgpums5zs4liXMGEvIHOfMpKs46CEKuy+v+X1ycK
-                HmCqgmspvyimFcxI84ajPlwwPL7JPU65h/b2w/SoMjnUyAF0Ae5KIUSLL0wp
-                DZO0OcLw99uXo8rbl0qoNaSEYuGzv/STJioNR6atodQNNZ4KDdcNhIYTo9Vq
-                PcnqaCIWUhtSsSS5trLh5Oy7X2In7BrPs+tpIHxaZO9+q45RnFQV2YRJW0XK
-                SFFZrUZJGSNlTVGpqLUyIWqf9EWnjYrRVrHGUawwKMVCU4FP/wMZ2qUbsn2p
-                YHvmnqHb+6Yw6QWdKr6qtKXTzia9C/Xzpm0sFvY2DHdFvrLyGXFy3Frlrinn
-                gbJm2cwTdMElOVOKe/yyngpQt+zx3O4Cfx5AxIt8DVpWlp2CmzMemnKtLYBc
-                LSOKEWrvKmqFMFLyTqC6fEWzavrG6JuSR7JMR6eiRBdDGyI0q8Iazb4LMJsH
-                krV/oGEw2UhjePIQTWtv0PZKtiC+DrwTaMQ6yQPkkSCcFNohW7MZHeiUXUtS
-                EmmylFIXusn3Gx8heorBt/RrDAeTo7EGUGtwHT0kS2I/kluEvunOyE+/IsIW
-                KhIMUxJyZDGfadLPR6VoSYJWiUmRdfMJ1mn0BqzTx6zTAWtZocx7VaijYoX6
-                zq3QjctX6ObVVKiNorX73dB8gnVphfoqViiLfvpKIh3+ClD1O2698qke1UPa
-                n8yrDUPQyr1ul3p1l3iN4U651/1Sr56SPv8ILUGppv18gN5DTFBRPj7ArUM8
-                WFPr3+DTA9w+xIwvf3aA+6+PQRNBERSi00zgYTyjuUKrM/gSq0Tre3/rnoLT
-                N0/6h7Qfj9YR1jGrQ9fxOeZ0zGNBxyIer4MJPMEX67gmMCAwKJAV6BcYppMt
-                MCSgCdwVuCcwJnBHICKwJNApkBRYFugS6Bbo+w//HMZ8gQ0AAA==
-                """,
-        """
-                androidx/navigation/NavGraph.class:
-                H4sIAAAAAAAA/31SXU8TQRQ9s6XbbUFaQBAq+AEoBZStxCdLSPwIWlOr0qYv
-                PE3bSZl+zJqdacNjf4v/wCeND6bx0R9lvLOtCkHcZO6de+65d87OnR8/v34D
-                8Bh7DKtcNcNANs98xQeyxY0MlF/mg5ch/3CaAGNYv4LxQmgjVRQmEGNwD6SS
-                5pAhltuuzSAON4UpJBimzKnUDLdK/zuqwLCghakYHppznRkWc6U2H3C/y1XL
-                f1tvi4YpbNdI+EH1yeXMYa5ajdIbpSBs+W1h6iGXSvtcqcBELbVfDky53+3S
-                kbP693nHQd8ID2nS2QlMVyq/Pej5UhkRKt71i8qE1EY2dAJzJKpxKhqdSZ93
-                POQ9QUSGrX+IPYdUbJNWwV7PAq6nMI9FhvnLJQxzpYmKN8LwJjecMKc3iNHY
-                mDVJa8DAOoSfSRvladd8xPB+NMymnGVnvDxaGSc1GpKzxnO8peXRcN/Js2fx
-                7x9dSr5ey8SyTn5q3fNGw0x8x8m7+24mkXVejQmebbzPsHnVAM/Ni2RaVVX6
-                g4uJvY6hl/A8aAqGdEkqUe736iKs8npX2DsIGrxb46G08QRMVmSLivsh7TeP
-                +8rIniiqgdSS0n8u/enfwTKkKkE/bIgjaetXJjW1ccU5Iu7CobdpP4fk0lMl
-                u0WRb8WTj+98hvcpSufIuhGYxDbZmTGBohT5OUwTEouKC8R2yCd25zNfsHSx
-                3CW6LV8aUybldpfGDcrvROxr2LWYFTEbAQ8iex8PyR8Rukwnr5wgVkS2iJtF
-                rGKNtrhVxG3cOQGzv7Z+gqRGSmNDw9WY1tjUuBfZtMbML5qRw8f+AwAA
-                """,
-        """
-                androidx/navigation/NavHost.class:
-                H4sIAAAAAAAA/31OTUvDQBB9s9F+xK9ELVTEv2Da4s2TUMRAVVDwktO2Wcs2
-                6S50t6HH/i4P0nN/lDiJd2fgzZt5w5vZ/3x9A7hDj3AtTb6yOt8kRlZ6Lr22
-                JnmR1ZN1vg0iRAtZyaSUZp68ThdqxtOAEE8K60ttkmflZS69vCeIZRWwLdXQ
-                rQEEKni+0XU3YJYPCb3dthOKvghFxOyzv9uOxIBqcUS4mfzzD99gy5i7sXJe
-                m0a8LTwhfLfr1Uw96lIRrt7Wxuul+tBOT0v1YIz1zapr8RUc4C8ELho8xyXX
-                ITsfcrYyBCnaKTopugiZ4ijFMU4ykMMpzjIIh8gh/gUZbPE0RgEAAA==
-                """,
-        """
-                androidx/navigation/Outer$InnerClass.class:
-                H4sIAAAAAAAA/41U30/bVhT+rp0fjgngAG35kbXdyFgS2jqwdusK7QZ0DLMQ
-                OpjQOvZySbxgCDazHdS9TDz1T6i0vUyapj3x0EobTKtUsfZtf9M07VzbTbrQ
-                IST7nnOPz/nOd88513/988czANexypDjds11rNoD3eZ7Vp37lmPry03fdHOG
-                bZvuXIN7XhKMQdvie1xvcLuuL29smVU/CZkhMW3Zln+HIZY3CmsMcr6wlkYc
-                SRUxKAyKJVBm3DoDM9JQ0ZWChDT5+5uWxzBWPguBKYauuukbLSxKYzCoVWdn
-                17FN258gwKqz+y1DgXicFXO07Lh1fcv0N1xu2Z7ObdvxA29Przh+pdloTInD
-                JFTifJ4hLVLkaubXvNnwGTbyZ0tkGOXO2k2dkWMa/RgQ2YeplL6z6ruWTccf
-                yBdegQytdJ4LnbbZptWomW4SF1VcEu0YaGPnX3bmtoI3qZF8d9e0awxX8yeh
-                T2aLkIngKHIC/G2GrCj9aY7vCMe8cJw73bEoHMfTyOINoV2lw29yb3POqZkM
-                mXakYftmXZyvFA4gTZiOSRUTeJdOZH7T5A2asXP519T/S5r909pPvecbDZOq
-                Gnf8TdNl6DuJQmTK247fsGx9yfR5jfucbNLOnkz3i4klJRbQ8G+T/YEldsRV
-                qtHA/ny8f1GVBiVV0o73VXokTVElJUGyi6RMskd5/lAZPN6flEpstrsvoUnD
-                Ukl+/lNC0mKLKS0pdgsvHsqL/ZpCOjkqihQ6kZmROUW6OqloXcOxQVZiCy8e
-                yRSYDj0eMdK7Se8R+kqmBa8QneGYEtcSguskEycY+t+BTWKe7mJ7sqgqFb53
-                1/R8yw7crm3TbYmF3estW7ZZae5smO7nosCirk6VN9a4a4l9ZBxZadq+tWMa
-                9p7lWWSaaTeHoXvV59XtJb4beec6ve9xl++YxO0/Yek2R5O26qrTdKvmvCUg
-                hiKItRPpaJok+pmJGvSJHxhpCun0W6B1kXbz9F0iqRaPkCqO/IbuJ7ST8Cmt
-                PRAt1ym+hBTJMu3Oh970rVcMB2kClaoGjd4QUxczQzJe/BXdBy24RGAsBTDp
-                0CGCyRC5l8GjncHstQH0ayFYETBBLAWn1FNI90eOcOFxKygkm2qRTUVklyI2
-                5wAthUEMRbnHomJlsrHvvociGEwXRw4xEkJWaJXBBAJd7ij9LZKCWvYpLt0/
-                wuW+tw4xJiIPUdAKh7hyiGuPO46RjRi9woNWvVWDsagGAYPfcb2zDEoUz3AD
-                70U8viIp2pUrjv+CeOxg/E9IPyAuH4wfQ1oSQFfo/VFYYmFPKkH75KTyNzJJ
-                2rcrlmtVLIeb+IDyLJOeFKTeD2pwLwil+4VPsEDl+ywANLBC8guy36JOTa1D
-                NjBt4LaBO/iQVHxkYAaz62Ae5nB3Hb2eeD72oAZrwoPmIeOhz0O/hxuB8aYH
-                3UOW9H8BSGQIivsHAAA=
-                """,
-        """
-                androidx/navigation/Outer$InnerObject.class:
-                H4sIAAAAAAAA/41US08TURT+7p0+plMe5SFPxQdFXsoUxBXEBFHjkFKMJRhl
-                dWlHGGhndOa2YcnKnVsXLl24YiFxQaKJqRI3/ijiudNREKIxac/5zrnnNd+5
-                Mz+OP30BMIvbDCPCLfueU941XVF3NoV0PNdcqUnbz1qua/srG9t2SSbBGDLb
-                oi7MinA3zV9ejSEx77iOvMOgjY2vtSCOhIEYkgwxueUEDKP5/+owx6BLryh9
-                x91k6B4bz590a3opYjjv+Zvmti03fOG4gSlc15NhwcAseLJQq1QoKn2qrI42
-                Krwlgq1Fr2yHQ1ra99nj1zS4/bImKjThhbH82SebG3/GkP1XN2olNio2tYt7
-                csv2GTrPV6HW86VKyI8BrkjRrUJxdaGweL8FAzBS5Bxk6MjveJLCzGVbirKQ
-                ghJ5ta7RjpgSKSXAwHbIv+soK0eoPM3wvLE3ZPA+bvBMY8/gugLpSOuGcmXa
-                9KNXRl9jb4bn2N2kzr+9S/AMX+rKaAM8F5vRM/GBWB/LsYdHb7SlVCZB3iRh
-                RlgnnFJYdZthaob+v24ziXF6lIKo37MD6bjhydSOZBh8XHOlU7Utt+4EDpG2
-                cEIkXZPmYtrzjmsXatUN219VxCo+vZKorAnfUXbkbC1KUdpZFi8iO3u29iPh
-                i6pN4/zRpCW8EosVEQQ2mUbRq/kl+4GjSvRHJdbODYdp2k8spL5frYv0DbIS
-                pFtJx+k0Hlo3yTLVgpR34hD6AQGOqSgYFGCSbGkGIEWlVNE0eXiYfDVK1jrb
-                P4RHJ+FaFH66M72L6Ij6nqR27v8llaEL3VEnizQn3Tsx+R7x2P7kV/C3iGv7
-                kw3wJ7H9cPAcyRh4Ug+L9TQTomIK9dCfETtQV5peIAI6+n5T0RsmAOnP4E8P
-                0f8RFw9Ch4YZkopHjgm0Eau3wn6T9C1SozFcInqG1qFZuGzhikVPd40ghi1k
-                MbIOFuA6RtdhBOo3FiARoCsEPQEyIUiT/AmvDPuL4QQAAA==
-                """,
-        """
-                androidx/navigation/Outer.class:
-                H4sIAAAAAAAA/4VRW2sTQRT+ZjaXzSbaNF6aWFsvTbWp4rbFp1qEGhUW0hRs
-                CUieJskQJ9nMwu4k9DFP/hD/QfGhoCBB3/xR4tltNA9S3GHPN+f2nTnn/Pz1
-                5RuA53jCUBG6Fwaqd+ZqMVF9YVSg3eOxkWEWjKE4EBPh+kL33ePOQHZNFhZD
-                5kBpZV4yWFu1VgFpZBykkGVImQ8qYlhtXMn6gsE+6PpJvgMeJ9le8+T0sFl/
-                U8A1ODkyXmfYaARh3x1I0wmF0pErtA5MwhO5zcA0x75PVMuNYWCIzD2SRvSE
-                EWTjo4lF3bFY5GIBBjYk+5mKtR269XYZarNpweFl7vDibOpw27J/fOTl2XSP
-                77B9bqVeZW3+/VOGF3mcsMdiGsfTWoZ1X0TUZD5RLqfCUL2y4+oiKYt7DJv/
-                ifwz5wfUXlNMXsvIKJ1EPRtSodV3Y23USHp6oiLV8eXhYjK0gHrQkwxLDaVl
-                czzqyPBUUAxDqRF0hd8SoYr1ubGweJqkZOckGIdd+VbFvsq8TuufKtilFaWS
-                uVbijRFWScsQFgk5nXSibZLmxtMnTG9fwD5P3I/mwcBTPCZZuAxAjqgAG/m/
-                ySsUHX/5r+DvL1D4jKXzxGBhi2SJ3PfpX6N3PCRcJ6wlJTawTbhPNMtEXGrD
-                8nDDw00Pt3CbrljxUEalDRbhDlbbSEdwItyNkImwFmH9NzJGDiwjAwAA
-                """,
-        """
-                androidx/navigation/OuterComp$InnerClassComp$Companion.class:
-                H4sIAAAAAAAA/51TTW/TQBB9a6dxYkJJUz4SoJRCgBRB3VQIIRUhQapKkdJW
-                giqXHtAmWcom9hp511GPOfFD+Ac9IXFAUY/8KMSsE6i4IJXLzJt582a0M/aP
-                n9++A3iGBsNzrgZJLAcngeJjecyNjFVwkBqRtOLoU72tFKGQa52F1nBFJR4Y
-                Q3nIxzwIuToODnpD0TceXIb8S6mkecXgNta7JSwg7yMHjyFnPkrN8KLzfyO3
-                GZqNzig2oVTBcBwFUpFE8TDYER94GppWrLRJ0r6Jkz2ejESyvd714djRy/X+
-                Ofk+yliGjYt1Y1j6LdgThg+44ZRzorFLy2TWFK0BAxtR/kTaaJPQoMlQn058
-                36k6vlMmNJ0Uzj671elky9lkb7yCc/Yl75QdW7vFbIcnF9mRh1sMK/9UeFhh
-                WPxbxlD8s1x62z4f7whtpMqkGyNDF2vFA8FwpSOV2E+jnkgOeS+kTKUT93nY
-                5Ym08TxZOm8v6M7+uzhN+mJXWq72NlVGRqIrtaTi10rFJpuj0aQT5ezeyDv2
-                c6Hn36MosIskv/D4KwqnGX2fbD5L7qJOtjQrQBE+UGaELs3FT8k7c3HpNDuK
-                FVyfJWeCDF3GInEuHlBUIfY27mAVtQzdJf8wG7yGR9kPQ7sgTfkIbhtLbVTa
-                WMZVgrjWpt43jsA0qqgRr+Fr3NTI/wIu2QAobQMAAA==
-                """,
-        """
-                androidx/navigation/OuterComp$InnerClassComp.class:
-                H4sIAAAAAAAA/5VUW08bVxD+zvq2XgysIRcHSJMWNzWGsECTlAJpuJelXFJI
-                aQjtw8HemgV7l+6urfSlylN+QqT2pVIf+sRDorZQFamiyVt/U1V1zu5ibhES
-                kn3OzOzMN9+ZmXP++e/PvwDcwdcMPdwqOrZZfKpZvGaWuGfalrZY9Qxnwq5s
-                Z3XLIqnMXVeoCTAGdZPXuFbmVklbXN80Cl4CEYb4iGmZ3icM0ZzetcIQyXWt
-                pBBDQkEUMoNsCqQxp8TA9BQUNCQhIUX+3obpMvTOXYTIMENDyfD0Oial0xmU
-                An2zLcPy+gm4YG9/x9BPfC6K3TlnOyVt0/DWHW5arsYty/b8KFdbsL2Fark8
-                LA4XV+gMVxhSIlW2aHzDq2WPwcldLKGuz52u6fAFOafQikuCTRuV2rOXPce0
-                qCyXcl3HoAMrne/qadt41SwXDSeBdxTcEO3KnMTPHXbvvox3qdl8e9uwigy3
-                c2fhz2YM0YlkJ7IiwfsMHaIt5zl+IBxzwnHifMe8cOxOoQPXhXSbCrDB3Y0J
-                u2gwpI8idcszSuKMfcGQ0hRqGFDQjw/pRMa3VV6mObyce0svnjBkzxsJmge+
-                XjaosjHb2zAchpazKMRrpFAOb8m9i3Q3KxZukUsCw2Ki57Zsj5C0zVpFM+lY
-                jsXL2mQwfhPEyHOqBc925rmzRUUKLuJ9BSOgzMk6GMPghYbsiAbVfRRj4gKP
-                U4kP2cwbHi9yjxNFqVKL0AvDxJIUC+jab5H9qSk06oBUpCu6c/DspiJlJEVS
-                D54p9JNUWZHkOO0NtEdobyKz/Pq5nCHX5gGpjw2x5vHGlrgqtUl9kdc/xyU1
-                OptUE0KbefM8MtuqyiQfPBuQZSlwIjMjc5JkZUBWG9qiGdbHZt68iFBgKvB4
-                wUhuJLlJyEvpOrxM+duickyNC84DTJzk+rlVS+AhQ9PJ0lGVFnht0nA90/Ld
-                e7fonWhfqlqeWTF0q2a6Jg3Q2NFQ0YwGE9w8Z1rGQrWybjiPxJCJ2bILvLzC
-                HVPoobFx2eOFrXm+HerZ09gPucMrBnE8kSR1xNMgVVm2q07BmDYFxLUQYuUM
-                ObozEj3roPWamASqySPS4rRfpr1FPO+i86THfOsXpE2Tt0S7kt9DMt/+Oxpf
-                +QgrtDZBjMUkYU5R1CS+JO1K4E3fmsUAkSRQqZJQ6R9gamKuaI/lf0PjTh0u
-                7hunfJhU4BDCpIncYXDn6WD21gB6WAlWBPQTS8EpuQ9ptX0PV1/WgwKyyTrZ
-                ZEj2WFnUJDJUriD3rbCA6Y7o9z9AFgxG8u27aA8gH9MaARMI9KyF6YdoF9Q6
-                9nFjdQ83W97bxS0RuYsutWsXPbvofXnqGB0ho+PtYVS2dJ1HUAOfwR+4c7oM
-                chjPcBf3Qh5f0S7alc13/4JYdKf7b0g/IhbZ6T6ANC+Aeuj/k7BEg5489tsX
-                Scj/Ip0g/ahi2XrFshjEx5RnleSEIPWRn34IiZBqxk9KxPYxssr28OBXTLzy
-                LRE88adOzNfnWKIij5A0Svuan36ZKINkRpMVw9QaIjqmdXyqYwY6iZjV8Rnm
-                yMHFPBbWoLpodrHoQvHXuCssaRctLlpd3PWNgy40Fx2+PPo/FBJ91lIJAAA=
-                """,
-        """
-                androidx/navigation/OuterComp$InnerObject.class:
-                H4sIAAAAAAAA/41US08TURT+7p0+plMe5SFPxQeoLVWmoK4gJoAah5RihGCU
-                1aUdy0A7gzO3DUtW/gQXLl3ohoXEBYkmpsrOH2U8dxgFIRKT9t7vnHvO+c58
-                5878+Pn5K4C7uMeQE27F95zKjumKplMV0vFcc6khbX/eq2+PWa5r+0vrm3ZZ
-                JsEYMpuiKcyacKvmb6/GkJhxXEfeZ9CyudU2xJEwEEOSISY3nIAhX/xvlmkG
-                XXrL0nfcKkNvNlc8ZjzyUsRo0fOr5qYt133huIEpXNeTYdHALHmy1KjVKCp9
-                oqyODiq8IYKNea9ih41amvuhMEPN268aokZdXsgWTz/ddO4Fw9h5bEQl1ms2
-                0cU9uWH7DN1nqxD1TLkWamSAK2F0q7S8Mluaf9iGIRgpcg4zdBW3PElh5qIt
-                RUVIQYm83tRoVkwtKbWAgW2Rf8dRVoFQZZLhZWt3xOAD3OCZ1q7BdQXS0a4b
-                ypXp0A9fGwOt3SleYHNJnX9/l+AZvtCT0YZ4ITalZ+JDsQFWYI8P32gLqUyC
-                vEnCjLBOOKWwYptiqodL5040iRw9Tkk0H9iBdNzwdGJLMgw/bbjSqduW23QC
-                h4SbPRaTrsvRcDqLjmuXGvV1219R4ipNvbKorQrfUXbkbF+Wory1KLYje+x0
-                7SfCF3WbWvqLpC28FvM1EQQ2mcay1/DL9iNHlRiMSqyeaQ6TNKNYKP+gGhnt
-                t8hK0N5Oe5xO46F1myxTDUl5xw+g7xPgmIiCgTk6BtqOApCiUqpomjw8TL4a
-                JWvdnR/Do+NwLQo/yUzvJLoi3uPU7r1/pDL0oDdismjntPeP598jHtvLfwN/
-                i7i2l2+BP4vthY0XaI2BJ/WwWN9RQlRMoT76M1IH6lrTS0RAx8AfKfrDBCD9
-                Bfz5AQY/4eJ+6NAwRavSkWMcHaTqnZAvT98l1RpdMZJnZA2ahcsWrlj0dNcI
-                YtTCGK6vgQW4gZtrMAL1ywZIBOgJQV+ATAjStP4Cqe39ku0EAAA=
-                """,
-        """
-                androidx/navigation/OuterComp.class:
-                H4sIAAAAAAAA/41RW2sTQRT+ZjaXzSa2abw0sbZVW7Wp4rbFp1qEGBUWYgq2
-                BCRPk2SJk2xmZWcS+pgnf4j/oPhQUJCgb/4o8ew2WkQo7rDnm3P7zpxzfvz8
-                /BXAEzxkWBWqF4Wyd+IqMZF9YWSo3MOx8aN6OHqfBWMoDsREuIFQffewM/C7
-                JguLIXMglTTPGKytaquANDIOUsgypMw7qRnWG5cyP2WwD7pBwuGAx4m21zw6
-                rjXrLwu4AidHxgWGjUYY9d2BbzqRkEq7QqnQJFzabYamOQ4ColpqDENDZO5r
-                34ieMIJsfDSxqEsWi1wswMCGZD+RsbZDt94uQ3U2LTi8zB1enE0dblv29w+8
-                PJvu8R22z63U86zNv33M8CKPE/ZYTLPgKUVtBELruBeGfGI4nw7Do0s73/w7
-                OYt1esR/ZPye/R1qtykmL3xtpEoiHw+p6MqbsTJy5HtqIrXsBH7tYlK0lHrY
-                8xkWG1L5zfGo40fHgmIYSo2wK4KWiGSsz42Fiyf6lOwcheOo67+Ssa8yr9P6
-                pwp2aWWpZM6VeIOEm6RlCIuEnE460e6R5sbbIExvn8E+Tdz358FADQ9IFs4D
-                kCMqwEb+T/IyRcdf/gv42zMUPmHxNDFY2CJZIvdt+lfpHXcJ1wirSYkNbBPu
-                E80SEZfasDxc9XDNw3XcoCuWPZRRaYNp3MRKG2kNR+OWRkZjVWPtF1d0yO47
-                AwAA
-                """,
-        """
-                androidx/navigation/TestAbstract.class:
-                H4sIAAAAAAAA/4VRy0oDMRQ9SduxHau29dX6AHUh6sLR4kJQhKoIA7WCSjeu
-                0s6gsdMMTNList/iH7gSXEhx6UeJN2P3bg7nkdwcbr5/Pj4BHGGdYUOoIIll
-                8OIpMZSPwshYefehNo2ONonomikwhtKzGAovEurRu+k8h9bNMDinUklzxpDZ
-                2W0XkYPjIosphqx5kpphq/nf8BOGcrMXm0gq7zo0IhBGkMf7wwwVZBYKFsDA
-                euS/SKsOiAWH1H08cl1e5S4vERuP8tvV8ajOD9h57uvV4SVuz9WZvV1uieEl
-                PSxVWmK/Z6jlRRyEDHNNqcLWoN8Jk3vRicipNOOuiNoikVZPTPcuHiTd8Epa
-                UbsdKCP7YVtqSWlDqdikg3V2E5yWMOlsd0JYJeWlGsjtvSP/RoSjRuik5jFW
-                CIt/B1CAm+arKS5jLf0shmnKig/I+JjxMetjDiWiKPuoYP4BTGMBi5RruBpL
-                Gs4vELgJXekBAAA=
-                """,
-        """
-                androidx/navigation/TestAbstractComp$Companion.class:
-                H4sIAAAAAAAA/5VSy27TQBQ9M07zMAHclkfCmzZILRJ1UrErQiqpkCLSIkGV
-                TRdo4gxlEnuMPBOry6z4EP6gKyQWKOqSj0LccQJs6ea+zj33+p7xz1/ffwB4
-                jicMO0KPslSNzkItcnUqrEp1eCyN3R8am4nIdtPkc8sZoQmqgDEEY5GLMBb6
-                NHw7HMvIVuAxlF8orexLBm9re1DHCso+SqgwlOwnZRja/cut2mPobPUnqY2V
-                Dsd5EiptZaZFHB7Ij2IaU7sm3jSyaXYosonM9rYHPrhbud6K/oEfkgKlWy83
-                jWH1D+FQWjESVlCNJ7lH4jFnas6AgU2ofqZc1qZo1GFozWe+zxvc5wFF81n1
-                4ovXmM92eZu9qlT5xdcyD7jr3WVuQut/tKngLkPtr0D0fUciP6AmpQvCzsSS
-                2t10JBmu95WWR9NkKLNjMYypstZPIxEPRKZcvizWe1rLrBsLYyS9kf8+nWaR
-                fK0c1nw31VYlcqCMouZ9rVNb7DHokMwldzt57p6aTnhIWejEIL/y9Buq5wX8
-                iGy5KL7BY7L1RQNq8IGAUXRlSX5Gni/J9fNCWEe4tSguCEV0FdcI87BBmV+Q
-                7uE+mtgsFj5Aq/i5SQPqDU7g9bDaw1oP67hBIW72aObtEzCDBpqEG/gGdwzK
-                vwGgwqXcGQMAAA==
-                """,
-        """
-                androidx/navigation/TestAbstractComp.class:
-                H4sIAAAAAAAA/41RW28SQRT+ZpfrulioN7BeWotI+9CljYmJNCaVxoRIMdGG
-                xPA0wIgDy6zZGUgf+S3+g8aHJpoY4qM/ynh2i+2DL7ycb87tO9858/vP958A
-                nmOXoczVIAzk4MxTfCaH3MhAeadCm6OeNiHvm0Yw+ZIGY8iP+Ix7PldD711v
-                JPomDZshdSiVNK8Y7OpOx0USKQcJpBkS5rPUDJXWKgPqDJnDvr+k2lulpRwZ
-                riiVhsuwX22NA0MM3mg28aQyIlTc947FJz71qUFR57RvgvCEh2MR1i/F3nSQ
-                wxpD9oqMobaS4uvxdRcFrGdh4RbDdisIh95ImF7IpdIeVyowMYP22oFpT32f
-                di3803oiDB9wwylmTWY2fQqLTDYyYGBjip/JyKvRa7BP91zMXccqWo6VX8wd
-                K2NlKsXFfNM+sGrsJbNfJ399TVl5K6o+YBFHoc1nxyReqljG3tgwbLyfKiMn
-                oqlmUsueL46uZdLPNYKBYFhrSSXa00lPhKecahjWW0Gf+x0eyshfBt2mUiJs
-                +FxrQc3Oh2Aa9sUbGeVKyzmd/6YktuheiXjJUnQ+wm3yUoR3CC3CZOyVyfOi
-                UxAmdy+QOY/TT5fFwFtUyLqXBcjCIczgxlVzEfEx4f5A7iO7QP4bbp/HERvP
-                yDpUlyPGAgmpxtxPsEP4guJ3ifFeF3YTxSZKTdzHBj3xoImHeNQF03iMzS4S
-                Go7GlkZKo/AX8BZ2A10DAAA=
-                """,
-        """
-                androidx/navigation/TestClass.class:
-                H4sIAAAAAAAA/31Ru04CQRQ9d4BFVlTAF/hs1cJFYqcxUYwJCWKihsZqYDc4
-                sMwmzEAs+Rb/wMrEwhBLP8p4d6W2OTmPO/femfn++fgEcIpdwq7U/ihS/oun
-                5UT1pFWR9h4DY+uhNCYLIhT6ciK9UOqed9fpB12bRYrgnCut7AUhdXDYziMD
-                x0UaWULaPitD2G/+2/mMUGwOIhsq7d0GVvrSSvbEcJLi1SiGXAwg0ID9FxWr
-                KjP/hLA3m7quKAtXFJjNpuXZtCaqdJX5enVEQcRVNYrPFltycs0zlU7mHw8s
-                L1iP/ICw0lQ6aI2HnWD0KDshO6Vm1JVhW45UrOem+xCNR93gRsWicj/WVg2D
-                tjKK00utI5s0NjiB4PvPN46fg7HMyks0kDl6x8IbE4EKo5OYB9hizP8VIAc3
-                ybcT3MRO8kmERc7yT0g1sNTAcgMrKDBFsYESVp9ABmtY59zANdgwcH4BpKME
-                iuEBAAA=
-                """,
-        """
-                androidx/navigation/TestClassComp$Companion.class:
-                H4sIAAAAAAAA/5VSTW8TMRB99qb5WAJsWz4SvtsGqQW121TcCkiQCilSWiSo
-                cukBOYkpTna9aO1EPebED+Ef9ITEAUU98qMQYyfAEfUynnnz3oz3eX/++v4D
-                wDM8Zngq9CDP1OAs1mKiToVVmY6PpbGtRBjTytLPDReEJrwExhANxUTEidCn
-                8dveUPZtCQFD8bnSyr5kCDa3ulUsoRiigBJDwX5ShmG7c4k9+wzNzc4os4nS
-                8XCSxkpbmWuRxAfyoxgntpVpY/Nx32b5ochHMt/f6obgbt9qo/+v+SH1XYad
-                y01jWP4jOJRWDIQVhPF0EpBtzIWKC2BgI8LPlKt2KRs0GRqzaRjyGg95RNls
-                Wr74EtRm0z2+y16Xyvzia5FH3HH3mJuw9l9jSrjLUPnrDl3uSEwOiKG0Z++M
-                LPncygaS4XpHaXk0TnsyPxa9hJCVTtYXSVfkytULsNrWWuZ+g6TXCd9n47wv
-                3yjXq78ba6tS2VVGEfmV1pn1ewya5HHBfTid3D0y3f8hVbFzgs6lJ99QPvft
-                RxSLHnyBNYrVOQEVhEDEKLuyEG/TyRfi6rl31QluzcG5wGdXcY16AdapCr3o
-                Hu6jjg2/8AEa/p8mD4gbnSBoY7mNlTZWcYNS3GzTzNsnYAY11KlvEBrcMSj+
-                BuBNy2UQAwAA
-                """,
-        """
-                androidx/navigation/TestClassComp.class:
-                H4sIAAAAAAAA/4VRXWsTQRQ9s5vPdWOT+pVYta2NmlZ0myIIpgqaIiykEbQE
-                JE+TZIyTbGZlZxL6mN/iPyg+FBQk+OiPEu9uY/vgQ1/umXvn3HPP3Pn95/tP
-                AM+ww7DJ1SAK5eDYU3wmh9zIUHlHQptmwLVuhpMvWTCG4ojPuBdwNfTe9Uai
-                b7KwGTL7UknzisGubXdcpJFxkEKWIWU+S82w1bpUvcGQ2+8HS53Hl/KrceCK
-                6lm4DPVaaxwaavdGs4knlRGR4oF3ID7xaWCaodImmvZNGB3yaCyixpnNqw4K
-                WGHIn4sxPLnc68XshosSVvOwcC1+ZRgNvZEwvYhLpT2uVGiSdu21Q9OeBgG9
-                svTP6KEwfMANp5o1mdn0ESwO+TiAgY2pfizjbJdOgzpDdTF3HatsOVZxMXes
-                nFVezDfsPWuXvWD2m/SvrxmraMXcPRYrlNp8dkC+pUpMPB0bhrX3U2XkRPhq
-                JrXsBeL1hUn6rmY4EAwrLalEezrpieiIE4dhtRX2edDhkYzzZdH1lRJRshVB
-                zc6HcBr1xVsZ31WWczr/TUGdtpVKnliJl0e4RVmG8AahRZhOsiplXrwIwvTO
-                KXInyfWDJRl4iYcU3TMC8nAIc7hy3lxGskq4P1D4yE5R/IbrJ0nFxiOKDvEK
-                pFgiI7VE+z62CZ9T/SYp3urC9lH2UfFxG2t0xB0fd3GvC6axjo0uUhqOxqZG
-                RqP0F+8+XexPAwAA
-                """,
-        """
-                androidx/navigation/TestClassWithArg.class:
-                H4sIAAAAAAAA/41QTWsTURQ9781kkoyJmcSvNFWrtpQ2Cyct7pRijAgDsUIt
-                cZHVSzKkr5m8gXkvocv8FtduBEVwIcGlP0q8b1JcuRBmzr3nvsO5H79+f/8B
-                4Bn2GPaEmmSpnFyFSizlVBiZqvA81qaXCK0/SHPRzaZFMIbgUixFmAg1Dd+N
-                LuOxKcJh8F5IJc0Jg3sQHQ4YnIPDQQUFFH24KBEX2ZSBRRX4uFEGR4Wk5kJq
-                hv3+//R+Tj2mselaGzKPGOr9WWoSqcK3sRETYQRJ+Hzp0ErMQtkCqOmM6lfS
-                sg5lkyOG3nrV8HmT+zxYr3z6eFDyeclprlfHvMNeVRtewFu84/z86PHAPav/
-                ZSVSt9xSIfCs1TGzDeqnYvmaxpUqH/3pzNBuvXQSM9T6UsWni/kozs7FKKFK
-                o5+ORTIQmbT8uui/TxfZOH4jLdk6Wygj5/FAakmvXaVSkxtrHNHh3Hyphr0j
-                ZZzyAjzCHWInxDlFv/0N5fb2V1Q/55pHhFYDtPGY8O5GhZuo2RtRZt1oEwT0
-                b7xCezqKhfYXVD/906ayEVzbcDzJ8SF2Kb7Mhyzg1hBOhNsR7kTU9h6laEbY
-                QmsIprGN+0MUNWoaDzT8HD2NQKP+B9uGEJmeAgAA
-                """,
-        """
-                androidx/navigation/TestClassWithArgComp$Companion.class:
-                H4sIAAAAAAAA/5VSy24TMRQ99qR5DAHSlkfC+xGkFIlOE3VXBCqpkCKlRaJV
-                WHSBnMS0TmY8yHaiLrPiQ/iDrpBYoKhLPgpxPQmwpZvre8+5597x8fz89f0H
-                gG08Y2gJPTSpGp5FWkzViXAq1dGRtK4dC2s/KHe6a07aafK57oPQRBfAGCoj
-                MRVRLPRJ9K4/kgNXQMCQf6m0cq8YgsZGr4wV5EPkUGDIuVNlGba7l1+3w9Bs
-                dMepi5WORtMkUtpJo0Uc7clPYhK7dqqtM5OBS82+MGNpdjZ6Ibhfu14f/CM/
-                JhnLsHm5aQyrfwT70omhcIIwnkwDMpH5UPIBDGxM+Jny1RZlwyZDfT4LQ17l
-                Ia9QNp8VL74E1fmsxbfYm0KRX3zN8wr3vS3mJzT+158C7jKU/ppE33ggpnvU
-                qHQm2hw7cr2dDiXD9a7S8mCS9KU5Ev2YkLVuOhBxTxjl6yVY7mgtTbZI0luF
-                h+nEDORb5bna+4l2KpE9ZRU172qdumyPRZOszvn708n9k9M1HlIVeUPoXHn+
-                DcXzjH5EMZ+Br/GYYnnRgBJCoMIou7IUv6CTL8Xl88xcL7i1ABeCLLuKa8QF
-                eEJVmInu4T5qeJotfIB69qOTB9RbOUbQwWoHax2s4waluNmhmbePwSyqqBFv
-                EVrcscj/BkiAeOUlAwAA
-                """,
-        """
-                androidx/navigation/TestClassWithArgComp.class:
-                H4sIAAAAAAAA/41SW08TQRT+ZnvZ7VpkWxELeEFBLVXZQngSgsEa4yalJkhq
-                DE/TdizTbmfN7rThkd/isy9EDYkmhvjojzKe3VZ40AeS3XPmnDnn+85lfv3+
-                9gPABtYYylx1wkB2jlzFR7LLtQyUuy8iXfN5FL2V+nAn7NaCwQcTjMHp8RF3
-                fa667utWT7S1iRRDdksqqbcZ0mVvpcmQKq8088jAtJGGRTYPuwzMy8PGlRwM
-                5ClUH8qIoVK/LP8m8XSF3omhiMBjsLba/oR4/bIoy7Hgiq5NXGNYK9f7gSYU
-                tzcauFJpESruuy/Eez70dS1QkQ6HbR2Euzzsi3Bz3Nd1GzOYZcidgzFsXLqR
-                ixI28yhhLh7IPMNSPQi7bk/oVsililyuVKATlMhtBLox9H0aQeFvvbtC8w7X
-                nHzGYJSidbJY5GIBGnaf/Ecytqp06tCmX50dF22jZNiGc3Zs02c4lm1Y6dLZ
-                8aK5blTZU2Y+nypmHWPeqKZ+fswaTnqvcG5ZlDKftjJONsZbZzFLocFHL6hF
-                qZJCV/uaYWFvqLQcCE+NZCRbvti5aITWXgs6gmG6LpVoDActEe5zimEo1oM2
-                95s8lLE9ceY9pUSYDFBQsv0mGIZt8VLGd3MTnuY/LFijiaapcwNz8YCp0ApZ
-                WdI3SRfjV0g6RXYm8T4ia5uiDdJ25RS5ysJXTJ0kCI8nmcAzPCE5O47CVUzH
-                k6ZTjEajgEP/GMuNF0A6U/mCqU//hcmPAyYwFhVlTpJLSFaI/HfMvGOnuPEZ
-                CyeJJ4XVhJDR6zOSxtwEewVV0jXy3yLE2wdIebjjYdHDXdyjI5Y8LOP+AViE
-                B3h4ACvCdIRyBDuR2QhOhEKE0h8DM7acGQQAAA==
-                """,
-        """
-                androidx/navigation/TestGraph.class:
-                H4sIAAAAAAAA/31SXWsTQRQ9M0k2m220af1oYq1Vmwf1wW2Lbxah1g8W1hVs
-                CJQ+TbJDOslmVnYnSx/z5A/xHxQfCgoS9M0fJd5Zgz4IzsC995w5c5h7mR8/
-                P38F8ARdhi2h4yxV8bmvRaFGwqhU+z2Zm9eZeH9WB2NojUUh/ETokf92MJZD
-                U0eFwTlQWplnDJUHD/tN1OB4qKLOUDVnKmfYDv/r/JTBPRgmpYcHbi+6QXTc
-                O4yOXjZxBV6DyKsMO2GajfyxNINMKJ37QuvUlF65H6UmmiUJWa2Fk9SQmf9G
-                GhELI4jj06JCXTIbGjaAgU2IP1cW7VIV7zF0F3PP423u8RZVi7n7/QNvL+b7
-                fJc9r7v820eHt7jV7jPrsBaJ4gU1oXT5iMcTw7D5bqaNmspAFypXg0Qe/n0k
-                zeMojSXDaqi0jGbTgcx6gjQM62E6FElfZMriJekdp7NsKF8pCzpL4/4/ttij
-                8VTLnjp2WpTvEHIotyhz2rUSbRPybeeUa48u4V6Ux3eXYqCLexSbvwVokBXg
-                YuXP5Q1S27XyBfzkEs1PWL0oCY77ZdzCTvmZaDZksH6KSoBrAa4HuIGbVGIj
-                QBudU7Act7BJ5zm8HLdzOL8ATyx+j4kCAAA=
-                """,
-        """
-                androidx/navigation/TestInterface.class:
-                H4sIAAAAAAAA/4VOTUvDQBB9s9GmjV+JWqhH8W7a0psnQYRAVVDxktM22ZZt
-                0g10t6HH/i4P0rM/SpzEH+AMvHkz83gz3z+fXwAm6BOupcnXlc63sZG1Xkin
-                KxO/K+sS49R6LjPlgwjhUtYyLqVZxC+zpcqcD48QTYvKldrET8rJXDp5RxCr
-                2mNzaqDXAAhU8Hyrm27ILB8R+vtdNxADEYiQ2Xyw343FkJrlmHAz/fcrvsTG
-                0bOsH3isTSu5LRwheKs260w96lIRrl43xumV+tBWz0p1b0zlWqnt8C0c4C8E
-                Llo8xyXXETsfcnZSeAn8BN0EPQRMcZTgGCcpyOIUZymERWgR/QKEKxfgUgEA
-                AA==
-                """,
-        """
-                androidx/navigation/TestNavHost.class:
-                H4sIAAAAAAAA/4VRu04CQRQ9d3koKyrgA/BF7NTCBWKnMfERIwlqooaGamA3
-                OLLMJsxAKPkW/8DKxMIQSz/KeHcxxsLEYk7O487MnTsfn69vAA5QIpSEcvuB
-                dEeOEkPZEUYGyrn3tLkWw8tAmxkQIfMohsLxheo4N61Hr81ujLD+19afbQlC
-                8kgqaY4JsZ3dRhozmLURR4oQNw9SE7br/1x+SMjWu4HxpXKuPCNcYQR7Vm8Y
-                4/4phFQIIFCX/ZEMVZmZWyFsTsa2bRWsaE3Ghcm4apXpNPH+lLQyVlhU5aI/
-                e/h1P9Nz7kiqKNnvGm7/LHA9wmJdKu960Gt5/XvR8tnJ1YO28BuiL0P9bdp3
-                waDf9i5kKIq3A2Vkz2tILTk9USow0cEaFVg8HZ7a9D3huBjXWDmRBhJ7L7Cf
-                mVhYZ0xGZh4bjOlpAeaYhflmhEVsRf9MmOdsoYlYDYs1ZGrIIscUSzUsY6UJ
-                0lhFnnONtEZBY/YLEThWOyQCAAA=
-                """,
-        """
-                androidx/navigation/TestObject.class:
-                H4sIAAAAAAAA/31S0WoTQRQ9M0k2m220aW1tYrVWW0R96LbFN4tQq8LCuoIN
-                AenTJDvESTazsDtZ+pgnP8Q/KH0oKEjQNz9KvLNGfRCcgXvvOXPmMPcy3398
-                +gLgCXYZtoSOs1TF574WhRoKo1Ltd2Vu3vRHcmDqYAytkSiEnwg99H+zFQbn
-                SGllnjFUHj7qNVGD46GKOkPVvFc5w3b4f+unDO7RIClNPHB70w2i0+5xdPKy
-                iWvwGkReZ9gJ02zoj6TpZ0Lp3Bdap6Y0y/0oNdE0SchqJRynhsz819KIWBhB
-                HJ8UFeqT2dCwAQxsTPy5smifqviAYXc+8zze5h5vUTWfud8+8PZ8dsj32fO6
-                y79+dHiLW+0hsw4rkSheUBdKl4/YGxuGzbdTbdREBrpQueon8vjvI2kgJ2ks
-                GZZDpWU0nfRl1hWkYVgN04FIeiJTFi9I7zSdZgP5SlnQWRj3/rHFAY2nWvbU
-                sdOivEXIodyizGnXSnSXkG87p1x7fAX3ojzeXoiBB7hHsflLgAZZAS6W/lze
-                ILVdS5/B312heYnli5LguF/GO9gpvxPNhgxWz1AJcCPAWoB13KQSGwHa6JyB
-                5biFTTrP4eW4ncP5CW9bciiLAgAA
-                """
-    )
diff --git a/navigation/navigation-runtime/build.gradle b/navigation/navigation-runtime/build.gradle
index f3a2d7e..2698334 100644
--- a/navigation/navigation-runtime/build.gradle
+++ b/navigation/navigation-runtime/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 
 plugins {
@@ -69,4 +71,5 @@
     inceptionYear = "2017"
     description = "Android Navigation-Runtime"
     legacyDisableKotlinStrictApiMode = true
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/paging/paging-common/build.gradle b/paging/paging-common/build.gradle
index 2bfc291..1c5792b 100644
--- a/paging/paging-common/build.gradle
+++ b/paging/paging-common/build.gradle
@@ -27,9 +27,9 @@
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import org.jetbrains.kotlin.konan.target.Family
 
+
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
@@ -39,7 +39,14 @@
     ios()
     watchos()
     tvos()
-    android()
+    androidLibrary {
+        namespace = "androidx.paging.common"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+    }
 
     defaultPlatform(PlatformIdentifier.JVM)
 
@@ -150,7 +157,3 @@
     metalavaK2UastEnabled = false
     samples(project(":paging:paging-samples"))
 }
-
-android {
-    namespace "androidx.paging.common"
-}
diff --git a/paging/paging-common/lint-baseline.xml b/paging/paging-common/lint-baseline.xml
new file mode 100644
index 0000000..c360e17
--- /dev/null
+++ b/paging/paging-common/lint-baseline.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.7.0-alpha02" type="baseline" client="gradle" dependencies="false" name="AGP (8.7.0-alpha02)" variant="all" version="8.7.0-alpha02">
+
+    <issue
+        id="NewApi"
+        message="This Kotlin extension function will be hidden by `java.util.SequencedCollection` starting in API 35"
+        errorLine1="            @OptIn(ExperimentalStdlibApi::class) repeat(result.size) { _hints.removeFirst() }"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/commonTest/kotlin/androidx/paging/PagingDataPresenterTest.kt"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="This Kotlin extension function will be hidden by `java.util.SequencedCollection` starting in API 35"
+        errorLine1="            @OptIn(ExperimentalStdlibApi::class) repeat(result.size) { _hints.removeFirst() }"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/commonTest/kotlin/androidx/paging/PagingDataPresenterTest.kt"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="This Kotlin extension function will be hidden by `java.util.SequencedCollection` starting in API 35"
+        errorLine1="    repeat(data.size) { removeFirst() }"
+        errorLine2="                        ~~~~~~~~~~~~~">
+        <location
+            file="src/commonTest/kotlin/androidx/paging/TestUtils.kt"/>
+    </issue>
+
+    <issue
+        id="BanThreadSleep"
+        message="Uses Thread.sleep()"
+        errorLine1="                Thread.sleep(1000)"
+        errorLine2="                       ~~~~~">
+        <location
+            file="src/commonJvmAndroidTest/kotlin/androidx/paging/PagedListTest.kt"/>
+    </issue>
+
+    <issue
+        id="BanThreadSleep"
+        message="Uses Thread.sleep()"
+        errorLine1="                    @Suppress(&quot;BlockingMethodInNonBlockingContext&quot;) Thread.sleep(100)"
+        errorLine2="                                                                           ~~~~~">
+        <location
+            file="src/commonJvmAndroidTest/kotlin/androidx/paging/SingleRunnerTest.kt"/>
+    </issue>
+
+</issues>
diff --git a/paging/paging-testing/build.gradle b/paging/paging-testing/build.gradle
index 9212202..50837cb 100644
--- a/paging/paging-testing/build.gradle
+++ b/paging/paging-testing/build.gradle
@@ -29,7 +29,6 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
 }
 
 androidXMultiplatform {
@@ -39,7 +38,14 @@
     ios()
     watchos()
     tvos()
-    android()
+    androidLibrary {
+        namespace = "androidx.paging.testing"
+        withAndroidTestOnDeviceBuilder {
+            it.compilationName = "instrumentedTest"
+            it.defaultSourceSetName = "androidInstrumentedTest"
+            it.sourceSetTreeName = "test"
+        }
+    }
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -131,6 +137,3 @@
     metalavaK2UastEnabled = false
 }
 
-android {
-    namespace "androidx.paging.testing"
-}
diff --git a/pdf/pdf-viewer-fragment/src/main/java/androidx/pdf/viewer/fragment/PdfViewerFragment.kt b/pdf/pdf-viewer-fragment/src/main/java/androidx/pdf/viewer/fragment/PdfViewerFragment.kt
index 59a2b5a7..d31fa8e 100644
--- a/pdf/pdf-viewer-fragment/src/main/java/androidx/pdf/viewer/fragment/PdfViewerFragment.kt
+++ b/pdf/pdf-viewer-fragment/src/main/java/androidx/pdf/viewer/fragment/PdfViewerFragment.kt
@@ -247,7 +247,6 @@
         fastScrollView = pdfViewer?.findViewById(R.id.fast_scroll_view)
         loadingView = pdfViewer?.findViewById(R.id.loadingView)
         paginatedView = fastScrollView?.findViewById(R.id.pdf_view)
-        paginationModel = paginatedView!!.paginationModel
         zoomView = pdfViewer?.findViewById(R.id.zoom_view)
         findInFileView = pdfViewer?.findViewById(R.id.search)
         findInFileView!!.setPaginatedView(paginatedView!!)
@@ -295,7 +294,7 @@
                     }
                     annotationButton?.let { button ->
                         if ((savedInstanceState == null) && isAnnotationIntentResolvable) {
-                            button.visibility = View.VISIBLE
+                            button.show()
                         }
                     }
                 },
@@ -456,6 +455,7 @@
             contents,
             pdfLoaderCallbacks!!
         )
+        setAnnotationIntentResolvability()
     }
 
     private fun setAnnotationIntentResolvability() {
@@ -484,7 +484,7 @@
                     isAnnotationIntentResolvable &&
                         state.getBoolean(KEY_ANNOTATION_BUTTON_VISIBILITY)
                 ) {
-                    annotationButton?.visibility = View.VISIBLE
+                    annotationButton?.show()
                 }
             }
         }
@@ -552,6 +552,7 @@
             SingleTapHandler(
                 requireContext(),
                 annotationButton!!,
+                paginatedView!!,
                 findInFileView!!,
                 zoomView!!,
                 selectionModel,
@@ -573,7 +574,7 @@
     }
 
     private fun refreshContentAndModels(pdfLoader: PdfLoader) {
-        paginationModel = paginatedView!!.initPaginationModelAndPageRangeHandler(requireActivity())
+        paginationModel = paginatedView!!.model
 
         paginatedView?.setPdfLoader(pdfLoader)
         findInFileView?.setPdfLoader(pdfLoader)
@@ -636,20 +637,19 @@
 
     override fun onResume() {
         super.onResume()
-        setAnnotationIntentResolvability()
         if (!documentLoaded) {
             return
         }
+        setAnnotationIntentResolvability()
+        if (!isAnnotationIntentResolvable && annotationButton?.visibility == View.VISIBLE) {
+            annotationButton?.post { annotationButton?.hide() }
+        }
         if (
             isAnnotationIntentResolvable &&
                 annotationButton?.visibility != View.VISIBLE &&
                 findInFileView?.visibility != View.VISIBLE
         ) {
-            annotationButton?.post {
-                annotationButton?.visibility = View.VISIBLE
-                annotationButton?.alpha = 0f
-                annotationButton?.animate()?.alpha(1f)?.setDuration(200)?.start()
-            }
+            annotationButton?.post { annotationButton?.show() }
         }
     }
 
@@ -705,10 +705,7 @@
 
     private fun detachViewsAndObservers() {
         zoomScrollObserver?.let { zoomView?.zoomScroll()?.removeObserver(it) }
-        paginatedView?.let { view ->
-            view.removeAllViews()
-            paginationModel?.removeObserver(view)
-        }
+        paginatedView?.let { view -> view.removeAllViews() }
     }
 
     override fun onDestroyView() {
@@ -753,6 +750,7 @@
             }
         if (pdfLoader != null) {
             pdfLoaderCallbacks?.uri = fileUri
+            paginatedView?.resetModels()
             destroyContentModel()
         }
         detachViewsAndObservers()
@@ -765,7 +763,7 @@
             onLoadDocumentError(e)
         }
         if (localUri != null && localUri != fileUri) {
-            annotationButton?.visibility = View.GONE
+            annotationButton?.hide()
         }
         localUri = fileUri
     }
diff --git a/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/widget/FastScrollViewIntegrationTest.kt b/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/widget/FastScrollViewIntegrationTest.kt
index 5eb44fd..647e77c 100644
--- a/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/widget/FastScrollViewIntegrationTest.kt
+++ b/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/widget/FastScrollViewIntegrationTest.kt
@@ -55,13 +55,12 @@
             // Start by adding a PaginatedView with 10 50x50 pages
             paginatedView =
                 PaginatedView(activity).apply {
-                    initPaginationModelAndPageRangeHandler(activity).apply {
+                    model.apply {
                         initialize(10)
                         for (i in 0..9) {
                             addPage(i, Dimensions(50, 50))
                         }
                     }
-                    model = paginationModel
                 }
             // Add a ZoomView to host the PaginatedView
             zoomView =
@@ -73,7 +72,7 @@
             fastScrollView =
                 FastScrollView(activity).apply {
                     layoutParams = ViewGroup.LayoutParams(100, 400)
-                    setPaginationModel(paginatedView.paginationModel)
+                    setPaginationModel(paginatedView.model)
                     addView(zoomView)
                 }
             activity.setContentView(fastScrollView)
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/find/FindInFileView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/find/FindInFileView.java
index aae1aa6..46be5f5 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/find/FindInFileView.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/find/FindInFileView.java
@@ -206,7 +206,7 @@
         if (visibility) {
             this.setVisibility(VISIBLE);
             if (mAnnotationButton != null && mAnnotationButton.getVisibility() == VISIBLE) {
-                mAnnotationButton.setVisibility(GONE);
+                mAnnotationButton.hide();
             }
             setupFindInFileBtn();
         } else {
@@ -233,7 +233,7 @@
             mQueryBox.setText("");
             parentLayout.setVisibility(GONE);
             if (mIsAnnotationIntentResolvable) {
-                mAnnotationButton.setVisibility(VISIBLE);
+                mAnnotationButton.show();
             }
         });
     }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/select/SelectionActionMode.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/select/SelectionActionMode.java
index 52ebbce..984cebb 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/select/SelectionActionMode.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/select/SelectionActionMode.java
@@ -192,21 +192,19 @@
             int screenWidth = mPaginatedView.getResources().getDisplayMetrics().widthPixels;
             int screenHeight = mPaginatedView.getResources().getDisplayMetrics().heightPixels;
 
-            if (pageSelection.getRects().size() == 1 || startHandlerect.intersect(0, 0, 
-                    screenWidth, screenHeight)) {
+            if (pageSelection.getRects().size() == 1 || startHandlerect.intersect(0, 0, screenWidth,
+                    screenHeight)) {
                 return pageSelection.getRects().getFirst();
             } else if (stopHandleRect.intersect(0, 0, screenWidth, screenHeight)) {
                 return pageSelection.getRects().getLast();
             } else {
                 // Center of the view in page coordinates
-                int viewCentreX =
-                        mPaginatedView.getPaginationModel().getViewArea().centerX() *
-                                mPaginatedView.getPaginationModel().getPageSize(
-                                        selectionPage).getWidth()
-                                        / mPaginatedView.getPaginationModel().getWidth();
-                int viewCentreY = mPaginatedView.getPaginationModel().getViewArea().centerY()
-                        - mPaginatedView.getPaginationModel().getPageLocation(selectionPage).top;
-
+                int viewCentreX = mPaginatedView.getViewArea().centerX()
+                        * mPaginatedView.getModel().getPageSize(selectionPage).getWidth()
+                        / mPaginatedView.getModel().getWidth();
+                int viewCentreY = mPaginatedView.getViewArea().centerY()
+                        - mPaginatedView.getModel().getPageLocation(selectionPage,
+                        mPaginatedView.getViewArea()).top;
                 return new Rect(viewCentreX, viewCentreY, viewCentreX, viewCentreY);
             }
         }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/AbstractPaginatedView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/AbstractPaginatedView.java
deleted file mode 100644
index 6575393..0000000
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/AbstractPaginatedView.java
+++ /dev/null
@@ -1,138 +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.pdf.viewer;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
-
-/**
- * Base class for views that will base their display on the {@link PaginationModel}.
- *
- * <p>Provides consistent {@link #onMeasure(int, int)} and {@link #onLayout(boolean, int, int, int,
- * int)} behavior and requests a layout each time a new page is added to the model.
- *
- * <p>Subclasses must implement {@link #layoutChild(int)} in order to position their actual views.
- * Subclasses can override {@link #onViewAreaChanged()} if they need to perform updates when this
- * happens.
- *
- * <p>Padding will not be acknowledged. If views must implement padding they need to measure
- * themselves but should be aware they will diverge from the coordinates of other views using the
- * {@link PaginationModel}.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-public abstract class AbstractPaginatedView extends ViewGroup implements PaginationModelObserver {
-
-    @Nullable
-    private PaginationModel mModel;
-
-    public AbstractPaginatedView(@NonNull Context context) {
-        super(context);
-    }
-
-    public AbstractPaginatedView(@NonNull Context context, @NonNull AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public AbstractPaginatedView(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    public void setModel(@Nullable PaginationModel model) {
-        this.mModel = model;
-    }
-
-    // This class does not produce a model but rather renders a model generated elsewhere to a view.
-    // Any classes wishing to obtain the model should do so from the owner/manager.
-    @Nullable
-    public PaginationModel getModel() {
-        return mModel;
-    }
-
-    protected boolean isInitialized() {
-        return mModel != null;
-    }
-
-    /**
-     * Measures this view in relation to the {@link #mModel} then asks all child views to measure
-     * themselves.
-     *
-     * <p>If the {@link #mModel} is not initialized, this view has nothing to display and will
-     * measure (0, 0). Otherwise, view will measure ({@link #mModel}'s width, {@link #mModel}'s
-     * estimated height).
-     */
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int width = 0;
-        int estimatedHeight = 0;
-
-        if (isInitialized()) {
-            width = mModel.getWidth();
-            estimatedHeight = mModel.getEstimatedFullHeight();
-        }
-
-        setMeasuredDimension(width, estimatedHeight);
-        measureChildren(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    /**
-     * Provides consistent layout behavior for subclasses.
-     *
-     * <p>Does not perform a layout if there aren't any child views. Otherwise asks the
-     * subclasses to
-     * layout each child by index.
-     */
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int count = getChildCount();
-        if (count == 0) {
-            return;
-        }
-
-        for (int i = 0; i < count; i++) {
-            layoutChild(i);
-        }
-    }
-
-    /**
-     * Lays out the child at {@code index}.
-     *
-     * <p>Subclasses should use the {@link #mModel} to determine top and bottom values.
-     */
-    protected abstract void layoutChild(int index);
-
-    /** Requests a layout because this view has to grow now to accommodate the new page(s). */
-    @Override
-    public void onPageAdded() {
-        requestLayout();
-    }
-
-    /**
-     * Implementation of PaginationModelObserver, is no-op at this level.
-     *
-     * <p>Will be called each time the viewArea of the model is changed. Should be overridden by any
-     * subclasses that wish to perform actions when this occurs.
-     */
-    @Override
-    public void onViewAreaChanged() {
-    }
-}
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageRangeHandler.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageRangeHandler.java
index 8936f4e..ea3ece28 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageRangeHandler.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageRangeHandler.java
@@ -56,11 +56,6 @@
         mMaxPage = maxPage;
     }
 
-    @NonNull
-    public PaginationModel getPaginationModel() {
-        return mPaginationModel;
-    }
-
     /**
      * Returns the page currently roughly centered in the view.
      */
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginatedView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginatedView.java
index f24d3da..3cdd35d 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginatedView.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginatedView.java
@@ -21,10 +21,12 @@
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.View;
+import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.pdf.ViewState;
 import androidx.pdf.data.Range;
 import androidx.pdf.util.PaginationUtils;
@@ -45,14 +47,11 @@
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 @SuppressWarnings("WrongCall")
-public class PaginatedView extends AbstractPaginatedView {
-
-    private static final String TAG = PaginatedView.class.getSimpleName();
-
+public class PaginatedView extends ViewGroup implements PaginationModelObserver {
     /** Maps the current child views to pages. */
     private final SparseArray<PageView> mPageViews = new SparseArray<>();
 
-    private PaginationModel mPaginationModel;
+    private PaginationModel mModel;
 
     private PageRangeHandler mPageRangeHandler;
 
@@ -68,6 +67,9 @@
 
     private boolean mIsConfigurationChanged = false;
 
+    /** The current viewport in content coordinates */
+    private final Rect mViewArea = new Rect();
+
     public PaginatedView(@NonNull Context context) {
         this(context, null);
     }
@@ -78,20 +80,112 @@
 
     public PaginatedView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-
+        mModel = new PaginationModel(context);
+        mPageRangeHandler = new PageRangeHandler(mModel);
     }
 
-    /** Instantiate PaginationModel and PageRangeHandler */
-    @NonNull
-    public PaginationModel initPaginationModelAndPageRangeHandler(@NonNull Context context) {
-        mPaginationModel = new PaginationModel(context);
-        mPageRangeHandler = new PageRangeHandler(mPaginationModel);
-        return mPaginationModel;
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mModel.addObserver(this);
+    }
+
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mPageRangeHandler != null) {
+            mPageRangeHandler.setVisiblePages(null);
+        }
+        mModel.removeObserver(this);
+    }
+
+    @VisibleForTesting
+    public void setModel(@NonNull PaginationModel model) {
+        mModel = model;
     }
 
     @NonNull
-    public PaginationModel getPaginationModel() {
-        return mPaginationModel;
+    public PaginationModel getModel() {
+        return mModel;
+    }
+
+    @NonNull
+    public PaginationModel resetModels() {
+        mModel = new PaginationModel(getContext());
+        mPageRangeHandler = new PageRangeHandler(mModel);
+        return mModel;
+    }
+
+    /** Requests a layout because this view has to grow now to accommodate the new page(s). */
+    @Override
+    public void onPageAdded() {
+        requestLayout();
+    }
+
+    protected boolean isInitialized() {
+        return mModel != null;
+    }
+
+    /**
+     * Measures this view in relation to the {@link #mModel} then asks all child views to measure
+     * themselves.
+     *
+     * <p>If the {@link #mModel} is not initialized, this view has nothing to display and will
+     * measure (0, 0). Otherwise, view will measure ({@link #mModel}'s width, {@link #mModel}'s
+     * estimated height).
+     */
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = 0;
+        int estimatedHeight = 0;
+
+        if (isInitialized()) {
+            width = mModel.getWidth();
+            estimatedHeight = mModel.getEstimatedFullHeight();
+        }
+
+        setMeasuredDimension(width, estimatedHeight);
+        measureChildren(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    /**
+     * Provides consistent layout behavior for subclasses.
+     *
+     * <p>Does not perform a layout if there aren't any child views. Otherwise asks the
+     * subclasses to
+     * layout each child by index.
+     */
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int count = getChildCount();
+        if (count == 0) {
+            return;
+        }
+
+        for (int i = 0; i < count; i++) {
+            layoutChild(i);
+        }
+    }
+
+    /**
+     * Returns the current viewport in content coordinates
+     */
+    @NonNull
+    public Rect getViewArea() {
+        return mViewArea;
+    }
+
+    /**
+     * Updates the current viewport
+     *
+     * @param viewArea the viewport in content coordinates
+     */
+    public void setViewArea(@NonNull Rect viewArea) {
+        if (!viewArea.equals(this.mViewArea)) {
+            this.mViewArea.set(viewArea);
+            onViewAreaChanged();
+        }
     }
 
     @NonNull
@@ -120,7 +214,7 @@
 
     @NonNull
     public PdfSelectionHandles getSelectionHandles() {
-        return  mSelectionHandles;
+        return mSelectionHandles;
     }
 
     public void setSelectionHandles(@NonNull PdfSelectionHandles selectionHandles) {
@@ -243,10 +337,10 @@
      *
      * @param index the index of the child view in this ViewGroup
      */
-    @Override
-    protected void layoutChild(int index) {
+    private void layoutChild(int index) {
         int pageNum = mPageViews.keyAt(index);
-        Rect pageCoordinates = getModel().getPageLocation(pageNum);
+        Rect viewArea = getViewArea();
+        Rect pageCoordinates = getModel().getPageLocation(pageNum, viewArea);
 
         PageView child = (PageView) getChildAt(index);
         child
@@ -257,7 +351,6 @@
                         pageCoordinates.right,
                         pageCoordinates.bottom);
 
-        Rect viewArea = getModel().getViewArea();
         child
                 .getPageView()
                 .setViewArea(
@@ -275,22 +368,13 @@
     }
 
     /** Perform a layout when the viewArea of the {@code model} has changed. */
-    @Override
-    public void onViewAreaChanged() {
+    private void onViewAreaChanged() {
         // We can't wait for the next layout pass, the pages will be drawn before.
         // We could still optimize to skip the next layoutChild() calls for the pages that have been
         // laid out already for this viewArea.
         onLayout(false, getLeft(), getTop(), getRight(), getBottom());
     }
 
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        if (mPageRangeHandler != null) {
-            mPageRangeHandler.setVisiblePages(null);
-        }
-    }
-
     /**
      * Refreshes the page range for the visible area.
      */
@@ -334,7 +418,7 @@
             if (getViewAt(pageNum) == null) {
                 mPageViewFactory.getOrCreatePageView(pageNum,
                         PaginationUtils.getPageElevationInPixels(getContext()),
-                        mPaginationModel.getPageSize(pageNum));
+                        mModel.getPageSize(pageNum));
                 requiresLayoutPass = true;
             }
         }
@@ -384,7 +468,7 @@
             PageMosaicView pageView = mPageViewFactory.getOrCreatePageView(
                     page,
                     PaginationUtils.getPageElevationInPixels(getContext()),
-                    mPaginationModel.getPageSize(page));
+                    mModel.getPageSize(page));
             pageView.clearTiles();
             pageView.requestFastDrawAtZoom(stableZoom);
             pageView.refreshPageContentAndOverlays();
@@ -396,7 +480,7 @@
             PageMosaicView pageView = mPageViewFactory.getOrCreatePageView(
                     page,
                     PaginationUtils.getPageElevationInPixels(getContext()),
-                    mPaginationModel.getPageSize(page));
+                    mModel.getPageSize(page));
             pageView.requestDrawAtZoom(stableZoom);
             pageView.refreshPageContentAndOverlays();
         }
@@ -417,7 +501,7 @@
             PageMosaicView pageView = mPageViewFactory.getOrCreatePageView(
                     page,
                     PaginationUtils.getPageElevationInPixels(getContext()),
-                    mPaginationModel.getPageSize(page));
+                    mModel.getPageSize(page));
             pageView.requestTiles();
         }
     }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModel.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModel.java
index f11e659..8407a743 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModel.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModel.java
@@ -50,19 +50,14 @@
  * <ol>
  *   <li>{@link #initialize(int)} with the number of pages it will contain.
  *   <li>{@link #addPage(int, Dimensions)} to set the dimensions for each page.
- *   <li>{@link #setViewArea(Rect)} to report current visible area so pages can be moved
- *       horizontally for maximum visibility.
  * </ol>
  *
  * <p>This model is observable. Any classes implementing {@link PaginationModelObserver} can
  * register themselves via {@link #addObserver(PaginationModelObserver)} and will be notified when
- * pages are added or the {@link #mViewArea} is changed.
+ * pages are added
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class PaginationModel {
-
-    private static final String TAG = PaginationModel.class.getSimpleName();
-
     /**
      * The spacing added before and after each page (the actual space between 2 consecutive pages is
      * twice this distance), in pixels.
@@ -86,22 +81,6 @@
 
     private int mAccumulatedPageSize = 0;
 
-    /**
-     * The portion of this model that is currently (or last we knew) exposed on the screen.
-     *
-     * <p>In the co-ordinates of this model - so if this entire model is within the visible area,
-     * then
-     * {@code viewArea} will contain the rect Rect(0, 0, getWidth, getHeight). Current visible area
-     * should be reported to this model via {@link #setViewArea(Rect)}.
-     */
-    private final Rect mViewArea = new Rect();
-
-    /**
-     * A temp working instance for computing {@link #mViewArea} to avoid excessive object
-     * creation.
-     */
-    private final Rect mTempViewArea = new Rect();
-
     private final Set<PaginationModelObserver> mObservers = new HashSet<>();
 
     public PaginationModel(@NonNull Context context) {
@@ -284,21 +263,7 @@
                 mMaxPages - mSize + 1));
     }
 
-    /**
-     * Updates the portion of this model that is visible on the screen, in this model's
-     * coordinates -
-     * so relative to (0, 0)-(getWidth(), getHeight()).
-     */
-    public void setViewArea(@NonNull Rect viewArea) {
-        mTempViewArea.set(viewArea);
-        if (!mTempViewArea.intersect(
-                0, 0, getWidth(), getEstimatedFullHeight())) { // Modifies tempViewArea.
-        }
-        if (!mTempViewArea.equals(this.mViewArea)) {
-            this.mViewArea.set(mTempViewArea);
-            notifyViewAreaChanged();
-        }
-    }
+
 
     /**
      * Returns the location of the page in the model.
@@ -313,10 +278,11 @@
      * </ul>
      *
      * @param pageNum - index of requested page
+     * @param viewArea - the current viewport in content coordinates
      * @return - coordinates of the page within this model
      */
     @NonNull
-    public Rect getPageLocation(int pageNum) {
+    public Rect getPageLocation(int pageNum, @NonNull Rect viewArea) {
         int left = 0;
         int right = getWidth();
         int top = mPageStops[pageNum];
@@ -324,15 +290,15 @@
         int width = mPages[pageNum].getWidth();
         if (width < right - left) {
             // this page is smaller than the view's width, it may slide left or right.
-            if (width < mViewArea.width()) {
+            if (width < viewArea.width()) {
                 // page is smaller than the view: center (but respect min left margin)
-                left = Math.max(left, mViewArea.left + (mViewArea.width() - width) / 2);
+                left = Math.max(left, viewArea.left + (viewArea.width() - width) / 2);
             } else {
                 // page is larger than view: scroll proportionally between the margins.
-                if (mViewArea.right > right) {
+                if (viewArea.right > right) {
                     left = right - width;
-                } else if (mViewArea.left > left) {
-                    left = mViewArea.left * (right - width) / (right - mViewArea.width());
+                } else if (viewArea.left > left) {
+                    left = viewArea.left * (right - width) / (right - viewArea.width());
                 }
             }
             right = left + width;
@@ -371,23 +337,6 @@
         return mMaxPages;
     }
 
-    /**
-     * Returns the intersection of this model and the last viewArea that was reported to this model
-     * via {@link #setViewArea(Rect)}.
-     */
-    @NonNull
-    public Rect getViewArea() {
-        return mViewArea;
-    }
-
-    /** Notify all observers that the {@code viewArea} has changed. */
-    private void notifyViewAreaChanged() {
-        Iterator<PaginationModelObserver> iterator = iterator();
-        while (iterator.hasNext()) {
-            iterator.next().onViewAreaChanged();
-        }
-    }
-
     /** Notify all observers that a page has been added to the model. */
     private void notifyPageAdded() {
         Iterator<PaginationModelObserver> iterator = iterator();
@@ -432,7 +381,7 @@
     @NonNull
     public Iterator<PaginationModelObserver> iterator() {
         synchronized (mObservers) {
-            return new ArrayList<PaginationModelObserver>(mObservers).iterator();
+            return new ArrayList<>(mObservers).iterator();
         }
     }
 
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModelObserver.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModelObserver.java
index 9619bfe..c404f42 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModelObserver.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PaginationModelObserver.java
@@ -35,13 +35,4 @@
      * Implementations are free to use this information as desired.
      */
     default void onPageAdded() {}
-
-    /**
-     * Notifies the implementation that the {@code viewArea} of the {@link PaginationModel} has
-     * changed.
-     *
-     * <p>The {@link PaginationModel} does not enforce any implementation expectations.
-     * Implementations are free to use this information as desired.
-     */
-    default void onViewAreaChanged() {}
 }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java
index 0fe8777..02df1c8 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java
@@ -229,7 +229,7 @@
         mFindInFileView = mPdfViewer.findViewById(R.id.search);
         mFastScrollView = mPdfViewer.findViewById(R.id.fast_scroll_view);
         mPaginatedView = mPdfViewer.findViewById(R.id.pdf_view);
-        mPaginationModel = mPaginatedView.getPaginationModel();
+        mPaginationModel = mPaginatedView.getModel();
         mZoomView = mPdfViewer.findViewById(R.id.zoom_view);
         mLoadingSpinner = mPdfViewer.findViewById(R.id.progress_indicator);
         setUpEditFab();
@@ -279,7 +279,7 @@
                 new SearchQueryObserver(mPaginatedView);
         mSearchModel.query().addObserver(mSearchQueryObserver);
 
-        mSingleTapHandler = new SingleTapHandler(getContext(), mAnnotationButton,
+        mSingleTapHandler = new SingleTapHandler(getContext(), mAnnotationButton, mPaginatedView,
                 mFindInFileView, mZoomView, mSelectionModel, mPaginationModel, mLayoutHandler);
         mPageViewFactory = new PageViewFactory(requireContext(), mPdfLoader,
                 mPaginatedView, mZoomView, mSingleTapHandler, mFindInFileView);
@@ -378,7 +378,6 @@
 
         if (mPaginatedView != null) {
             mPaginatedView.removeAllViews();
-            mPaginationModel.removeObserver(mPaginatedView);
             mPaginatedView = null;
         }
 
@@ -627,8 +626,6 @@
                         mPaginatedView.getPageRangeHandler().setMaxPage(1);
                         if (viewState().get() != ViewState.NO_VIEW) {
                             mPaginationModel.initialize(numPages);
-                            mPaginatedView.setModel(mPaginationModel);
-                            mPaginationModel.addObserver(mPaginatedView);
                             mFastScrollView.setPaginationModel(mPaginationModel);
 
                             dismissPasswordDialog();
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/SingleTapHandler.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/SingleTapHandler.java
index 74f02a6..67cfb2d 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/SingleTapHandler.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/SingleTapHandler.java
@@ -38,6 +38,7 @@
 public class SingleTapHandler {
     private final Context mContext;
     private final FloatingActionButton mFloatingActionButton;
+    private final PaginatedView mPaginatedView;
     private final FindInFileView mFindInFileView;
     private final ZoomView mZoomView;
     private final PdfSelectionModel mPdfSelectionModel;
@@ -47,6 +48,7 @@
 
     public SingleTapHandler(@NonNull Context context,
             @NonNull FloatingActionButton floatingActionButton,
+            @NonNull PaginatedView paginatedView,
             @NonNull FindInFileView findInFileView,
             @NonNull ZoomView zoomView,
             @NonNull PdfSelectionModel pdfSelectionModel,
@@ -54,6 +56,7 @@
             @NonNull LayoutHandler layoutHandler) {
         mContext = context;
         mFloatingActionButton = floatingActionButton;
+        mPaginatedView = paginatedView;
         mFindInFileView = findInFileView;
         mZoomView = zoomView;
         mPdfSelectionModel = pdfSelectionModel;
@@ -65,15 +68,14 @@
         mIsAnnotationIntentResolvable = annotationIntentResolvable;
     }
 
-    /** */
     public void handleSingleTapConfirmedEventOnPage(@NonNull MotionEvent event,
             @NonNull PageMosaicView pageMosaicView) {
         if (mIsAnnotationIntentResolvable) {
             if (mFloatingActionButton.getVisibility() == View.GONE
                     && mFindInFileView.getVisibility() == GONE) {
-                mFloatingActionButton.setVisibility(View.VISIBLE);
+                mFloatingActionButton.show();
             } else {
-                mFloatingActionButton.setVisibility(View.GONE);
+                mFloatingActionButton.hide();
             }
         }
 
@@ -123,7 +125,8 @@
         if (destination.getYCoordinate() != null) {
             int pageY = (int) destination.getYCoordinate().floatValue();
 
-            Rect pageRect = mPaginationModel.getPageLocation(destination.getPageNumber());
+            Rect pageRect = mPaginationModel.getPageLocation(destination.getPageNumber(),
+                    mPaginatedView.getViewArea());
             int x = pageRect.left + (pageRect.width() / 2);
             int y = mPaginationModel.getLookAtY(destination.getPageNumber(), pageY);
             // Zoom should match the width of the page.
@@ -155,7 +158,7 @@
             return;
         }
 
-        Rect pageRect = mPaginationModel.getPageLocation(pageNum);
+        Rect pageRect = mPaginationModel.getPageLocation(pageNum, mPaginatedView.getViewArea());
 
         int x = pageRect.left + (pageRect.width() / 2);
         int y = pageRect.top + (pageRect.height() / 2);
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/ZoomScrollValueObserver.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/ZoomScrollValueObserver.java
index 4d83cc3..b266f91 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/ZoomScrollValueObserver.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/ZoomScrollValueObserver.java
@@ -16,7 +16,6 @@
 
 package androidx.pdf.viewer;
 
-import android.animation.ValueAnimator;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
@@ -45,7 +44,6 @@
     private final SelectionActionMode mSelectionActionMode;
     private final ObservableValue<ViewState> mViewState;
 
-    private static final int FAB_ANIMATION_DURATION = 200;
     private boolean mIsPageScrollingUp;
 
     public ZoomScrollValueObserver(@Nullable ZoomView zoomView,
@@ -69,13 +67,11 @@
     @Override
     public void onChange(@Nullable ZoomView.ZoomScroll oldPosition,
             @Nullable ZoomView.ZoomScroll position) {
-        if (mPaginatedView == null || !mPaginatedView.getPaginationModel().isInitialized()
-                || position == null || mPaginatedView.getPaginationModel().getSize() == 0) {
+        if (mPaginatedView == null || !mPaginatedView.getModel().isInitialized()
+                || position == null || mPaginatedView.getModel().getSize() == 0) {
             return;
         }
-        // Stop showing context menu if there is any change in zoom or scroll, resume only when
-        // the new position is stable
-        mSelectionActionMode.stopActionMode();
+
         mZoomView.loadPageAssets(mLayoutHandler, mViewState);
 
         if (oldPosition.scrollY > position.scrollY) {
@@ -84,11 +80,20 @@
             mIsPageScrollingUp = false;
         }
 
+        // Stop showing context menu if there is any change in zoom or scroll, resume only when
+        // the new position is stable
+        if (mPaginatedView.getSelectionModel().selection().get() != null) {
+            mSelectionActionMode.stopActionMode();
+            if (position.stable) {
+                setUpContextMenu();
+            }
+        }
+
         if (mIsAnnotationIntentResolvable && !mPaginatedView.isConfigurationChanged()) {
 
             if (!isAnnotationButtonVisible() && position.scrollY == 0
                     && mFindInFileView.getVisibility() == View.GONE) {
-                editFabExpandAnimation();
+                mAnnotationButton.show();
             } else if (isAnnotationButtonVisible() && mIsPageScrollingUp) {
                 clearAnnotationHandler();
                 return;
@@ -98,16 +103,7 @@
                     @Override
                     public void run() {
                         if (position.scrollY != 0) {
-                            mAnnotationButton.animate()
-                                    .alpha(0.0f)
-                                    .setDuration(FAB_ANIMATION_DURATION)
-                                    .withEndAction(new Runnable() {
-                                        @Override
-                                        public void run() {
-                                            mAnnotationButton.setVisibility(View.GONE);
-                                            mAnnotationButton.setAlpha(1.0f);
-                                        }
-                                    });
+                            mAnnotationButton.hide();
                         }
                     }
                 });
@@ -116,35 +112,12 @@
                 && position.scrollY != oldPosition.scrollY) {
             mPaginatedView.setConfigurationChanged(false);
         }
-
-        if (mPaginatedView.getSelectionModel().selection().get() != null && position.stable) {
-            setUpContextMenu();
-        }
     }
 
     private boolean isAnnotationButtonVisible() {
         return mAnnotationButton.getVisibility() == View.VISIBLE;
     }
 
-    private void editFabExpandAnimation() {
-        mAnnotationButton.setScaleX(0.0f);
-        mAnnotationButton.setScaleY(0.0f);
-        ValueAnimator scaleAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
-        scaleAnimator.setDuration(FAB_ANIMATION_DURATION);
-        scaleAnimator.addUpdateListener(
-                new ValueAnimator.AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(@NonNull ValueAnimator animation) {
-                        float scale = (float) animation.getAnimatedValue();
-                        mAnnotationButton.setScaleX(scale);
-                        mAnnotationButton.setScaleY(scale);
-                        mAnnotationButton.setAlpha(scale);
-                    }
-                });
-        scaleAnimator.start();
-        mAnnotationButton.setVisibility(View.VISIBLE);
-    }
-
     /** Exposing a function to clear the handler when PDFViewer Fragment is destroyed. */
     public void clearAnnotationHandler() {
         mAnnotationButtonHandler.removeCallbacksAndMessages(null);
@@ -167,16 +140,16 @@
             if (selectionPage >= firstPageInVisibleRange
                     && selectionPage <= lastPageInVisisbleRange) {
                 // Start and stop coordinates in a page wrt pagination model
-                int startX = mPaginatedView.getPaginationModel().getLookAtX(selectionPage,
+                int startX = mPaginatedView.getModel().getLookAtX(selectionPage,
                         mPaginatedView.getSelectionModel().selection().get().getStart().getX());
-                int startY = mPaginatedView.getPaginationModel().getLookAtY(selectionPage,
+                int startY = mPaginatedView.getModel().getLookAtY(selectionPage,
                         mPaginatedView.getSelectionModel().selection().get().getStart().getY());
-                int stopX = mPaginatedView.getPaginationModel().getLookAtX(selectionPage,
+                int stopX = mPaginatedView.getModel().getLookAtX(selectionPage,
                         mPaginatedView.getSelectionModel().selection().get().getStop().getX());
-                int stopY = mPaginatedView.getPaginationModel().getLookAtY(selectionPage,
+                int stopY = mPaginatedView.getModel().getLookAtY(selectionPage,
                         mPaginatedView.getSelectionModel().selection().get().getStop().getY());
 
-                Rect currentViewArea = mPaginatedView.getPaginationModel().getViewArea();
+                Rect currentViewArea = mPaginatedView.getViewArea();
 
                 if (currentViewArea.intersect(startX, startY, stopX, stopY)) {
                     mSelectionActionMode.resume();
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/loader/PdfLoaderCallbacksImpl.kt b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/loader/PdfLoaderCallbacksImpl.kt
index f614d30..b5fbe27 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/loader/PdfLoaderCallbacksImpl.kt
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/loader/PdfLoaderCallbacksImpl.kt
@@ -117,28 +117,27 @@
             return
         }
 
-        if (selection.page >= paginatedView.paginationModel.size) {
+        if (selection.page >= paginatedView.model.size) {
             layoutHandler!!.layoutPages(selection.page + 1)
             return
         }
 
         val rect = selection.pageMatches.getFirstRect(selection.selected)
-        val x: Int = paginatedView.paginationModel.getLookAtX(selection.page, rect.centerX())
-        val y: Int = paginatedView.paginationModel.getLookAtY(selection.page, rect.centerY())
+        val x: Int = paginatedView.model.getLookAtX(selection.page, rect.centerX())
+        val y: Int = paginatedView.model.getLookAtY(selection.page, rect.centerY())
         zoomView.centerAt(x.toFloat(), y.toFloat())
 
         pageViewFactory!!
             .getOrCreatePageView(
                 selection.page,
                 pageElevationInPixels,
-                paginatedView.paginationModel.getPageSize(selection.page)
+                paginatedView.model.getPageSize(selection.page)
             )
             .setOverlay(selection.overlay)
     }
 
     private fun isPageCreated(pageNum: Int): Boolean {
-        return pageNum < paginatedView.paginationModel.size &&
-            paginatedView.getViewAt(pageNum) != null
+        return pageNum < paginatedView.model.size && paginatedView.getViewAt(pageNum) != null
     }
 
     private fun getPage(pageNum: Int): PageViewFactory.PageView? {
@@ -198,16 +197,12 @@
         paginatedView.pageRangeHandler.maxPage = 1
         if (viewState.get() != ViewState.NO_VIEW) {
             if (uri != null && data.uri == uri) {
-                paginatedView.paginationModel.setMaxPages(-1)
+                paginatedView.model.setMaxPages(-1)
             }
 
-            paginatedView.paginationModel.initialize(numPages)
+            paginatedView.model.initialize(numPages)
 
-            // Add pagination model to the view
-            paginatedView.model = paginatedView.paginationModel
-            paginatedView.let { paginatedView.paginationModel.addObserver(it) }
-
-            fastScrollView.setPaginationModel(paginatedView.paginationModel)
+            fastScrollView.setPaginationModel(paginatedView.model)
 
             dismissPasswordDialog()
 
@@ -249,12 +244,12 @@
 
     override fun pageBroken(page: Int) {
         if (viewState.get() != ViewState.NO_VIEW) {
-            if (page < paginatedView.paginationModel.numPages) {
+            if (page < paginatedView.model.numPages) {
                 pageViewFactory!!
                     .getOrCreatePageView(
                         page,
                         pageElevationInPixels,
-                        paginatedView.paginationModel.getPageSize(page)
+                        paginatedView.model.getPageSize(page)
                     )
                     .setFailure(context.resources.getString(R.string.error_on_page, page + 1))
                 // TODO: Track render error.
@@ -265,9 +260,9 @@
     override fun setPageDimensions(pageNum: Int, dimensions: Dimensions) {
         if (viewState.get() != ViewState.NO_VIEW) {
 
-            paginatedView.paginationModel.addPage(pageNum, dimensions)
+            paginatedView.model.addPage(pageNum, dimensions)
 
-            layoutHandler!!.pageLayoutReach = paginatedView.paginationModel.size
+            layoutHandler!!.pageLayoutReach = paginatedView.model.size
 
             if (
                 searchModel!!.query().get() != null &&
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/password/PasswordDialog.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/password/PasswordDialog.java
index 92636fa..a994a5d 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/password/PasswordDialog.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/password/PasswordDialog.java
@@ -185,7 +185,7 @@
     public void onStart() {
         super.onStart();
         mTextDefaultColor = getResources().getColor(R.color.pdf_viewer_color_on_surface);
-        mTextErrorColor = getResources().getColor(R.color.pdf_viewer_color_on_error);
+        mTextErrorColor = getResources().getColor(R.color.pdf_viewer_color_error);
         mBlueColor = getResources().getColor(R.color.pdf_viewer_color_primary);
 
         EditText textField = (EditText) getDialog().findViewById(R.id.password);
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/ZoomView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/ZoomView.java
index d7755ef..e5a021c 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/ZoomView.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/ZoomView.java
@@ -902,7 +902,7 @@
 
         PaginatedView paginatedView = this.findViewById(R.id.pdf_view);
         ZoomScroll position = this.zoomScroll().get();
-        if (position == null || !paginatedView.getPaginationModel().isInitialized()) {
+        if (position == null || !paginatedView.getModel().isInitialized()) {
             return;
         }
 
@@ -911,7 +911,7 @@
             this.setStableZoom(position.zoom);
         }
 
-        paginatedView.getPaginationModel().setViewArea(this.getVisibleAreaInContentCoords());
+        paginatedView.setViewArea(this.getVisibleAreaInContentCoords());
         paginatedView.refreshPageRangeInVisibleArea(position, this.getHeight());
         paginatedView.handleGonePages(false);
         paginatedView.loadInvisibleNearPageRange(this.getStableZoom());
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 269c461..3efa5d2 100644
--- a/pdf/pdf-viewer/src/main/res/values-af/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-af/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Kon nie die lêer oopmaak nie. Moontlike toestemmingkwessie?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Bladsy is vir die PDF-dokument gebreek"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Onvoldoende data om die PDF-dokument te verwerk"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 517f867..a2679692 100644
--- a/pdf/pdf-viewer/src/main/res/values-am/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-am/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ፋይሉን መክፈት አልተሳካም። የፈቃድ ችግር ሊሆን ይችላል?"</string>
     <string name="page_broken" msgid="2968770793669433462">"ለPDF ሰነዱ ገፅ ተበላሽቷል"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ሰነዱን ለማሰናዳት በቂ ያልሆነ ውሂብ"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 3b33c01..eae5948 100644
--- a/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"تعذّر فتح الملف. هل توجد مشكلة محتملة في الأذونات؟"</string>
     <string name="page_broken" msgid="2968770793669433462">"‏تعذّر تحميل صفحة من مستند PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"‏البيانات غير كافية لمعالجة مستند PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 6aff8a9eb..f9c9ef7 100644
--- a/pdf/pdf-viewer/src/main/res/values-as/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-as/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ফাইলটো খুলিব পৰা নগ’ল। সম্ভাব্য অনুমতি সম্পৰ্কীয় সমস্যা?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF নথিৰ বাবে পৃষ্ঠাখন বিসংগতিপূৰ্ণ"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF নথিখন প্ৰক্ৰিয়াকৰণ কৰিবলৈ অপৰ্যাপ্ত ডেটা"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 622b95f..6ef1751 100644
--- a/pdf/pdf-viewer/src/main/res/values-az/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-az/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Fayl açılmadı. İcazə problemi var?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF sənədi üçün səhifədə xəta var"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF sənədini emal etmək üçün kifayət qədər data yoxdur"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 0495044..f259654 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Otvaranje fajla nije uspelo. Možda postoje problemi sa dozvolom?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Neispravna stranica za PDF dokument"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nedovoljno podataka za obradu PDF dokumenta"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 6d25879..c951b2c 100644
--- a/pdf/pdf-viewer/src/main/res/values-be/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-be/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Не ўдалося адкрыць файл. Магчыма, праблема з дазволам?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Старонка дакумента PDF пашкоджана"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Не хапае даных для апрацоўкі дакумента PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 37f6840..004be66 100644
--- a/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"Файлът не бе отворен. Възможно е да има проблем с разрешенията."</string>
     <string name="page_broken" msgid="2968770793669433462">"Невалидна страница в PDF документа"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Няма достатъчно данни за обработването на PDF документа"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"PDF файлът не може да се отвори"</string>
 </resources>
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 a65a18c..937be09 100644
--- a/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ফাইল খোলা যায়নি। অনুমতি সংক্রান্ত সমস্যার কারণে এটি হতে পারে?"</string>
     <string name="page_broken" msgid="2968770793669433462">"পিডিএফ ডকুমেন্টের ক্ষেত্রে পৃষ্ঠা ভেঙে গেছে"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"পিডিএফ ডকুমেন্ট প্রসেস করার জন্য যথেষ্ট ডেটা নেই"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 642b643..cd49b7a 100644
--- a/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Otvaranje fajla nije uspjelo. Možda postoji problem s odobrenjem?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Stranica je prelomljena za PDF dokument"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nema dovoljno podataka za obradu PDF dokumenta"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 9338452..4f3deac 100644
--- a/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"No s\'ha pogut obrir el fitxer. És possible que hi hagi un problema de permisos?"</string>
     <string name="page_broken" msgid="2968770793669433462">"La pàgina no funciona per al document PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Les dades són insuficients per processar el document PDF"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"No es pot obrir el fitxer PDF"</string>
 </resources>
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 07d4e4e..cdc4b65 100644
--- a/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Soubor se nepodařilo otevřít. Může se jednat o problém s oprávněním."</string>
     <string name="page_broken" msgid="2968770793669433462">"Dokument PDF obsahuje poškozenou stránku"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nedostatek dat ke zpracování dokumentu PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 9ad79da..5bcd02c 100644
--- a/pdf/pdf-viewer/src/main/res/values-da/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-da/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Filen kunne ikke åbnes Mon der er et problem med tilladelserne?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Siden er ødelagt for PDF-dokumentet"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Der er ikke nok data til at behandle PDF-dokumentet"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 45bac2a..72b1096 100644
--- a/pdf/pdf-viewer/src/main/res/values-de/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-de/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Datei konnte nicht geöffnet werden. Möglicherweise ein Berechtigungsproblem?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Seite für PDF-Dokument ist fehlerhaft"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Keine ausreichenden Daten, um das PDF-Dokument zu verarbeiten"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 e87a5b8..ada33d8 100644
--- a/pdf/pdf-viewer/src/main/res/values-el/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-el/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Δεν ήταν δυνατό το άνοιγμα του αρχείου. Μήπως υπάρχει κάποιο πρόβλημα με την άδεια;"</string>
     <string name="page_broken" msgid="2968770793669433462">"Δεν ήταν δυνατή η φόρτωση του εγγράφου PDF από τη σελίδα"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Μη επαρκή δεδομένα για την επεξεργασία του εγγράφου PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 62dcae9..2f9e726 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Failed to open the file. Possible permission issue?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Page broken for the PDF document"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Insufficient data for processing the PDF document"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 5a09605..66f8a08 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
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"Failed to open the file. Possible permission issue?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Page broken for the PDF document"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Insufficient data for processing the PDF document"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"Can\'t open PDF file"</string>
 </resources>
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 62dcae9..2f9e726 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Failed to open the file. Possible permission issue?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Page broken for the PDF document"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Insufficient data for processing the PDF document"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 62dcae9..2f9e726 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Failed to open the file. Possible permission issue?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Page broken for the PDF document"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Insufficient data for processing the PDF document"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rXC/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rXC/strings.xml
index d2bf4b8..f0cfb06 100644
--- a/pdf/pdf-viewer/src/main/res/values-en-rXC/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-en-rXC/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎Failed to open the file. Possible permission issue?‎‏‎‎‏‎"</string>
     <string name="page_broken" msgid="2968770793669433462">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‎Page broken for the PDF document‎‏‎‎‏‎"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎Insufficient data for processing the PDF document‎‏‎‎‏‎"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‎Can\'t open PDF file‎‏‎‎‏‎"</string>
 </resources>
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 4ad89b2..388c071 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
@@ -42,12 +42,9 @@
     <string name="desc_page_range" msgid="5286496438609641577">"páginas <xliff:g id="FIRST">%1$d</xliff:g> a <xliff:g id="LAST">%2$d</xliff:g> de <xliff:g id="TOTAL">%3$d</xliff:g>"</string>
     <string name="desc_image_alt_text" msgid="7700601988820586333">"Imagen: <xliff:g id="ALT_TEXT">%1$s</xliff:g>"</string>
     <string name="hint_find" msgid="5385388836603550565">"Buscar en el archivo"</string>
-    <!-- no translation found for previous_button_description (1169511027880317546) -->
-    <skip />
-    <!-- no translation found for next_button_description (4702699322249103693) -->
-    <skip />
-    <!-- no translation found for close_button_description (7379823906921067675) -->
-    <skip />
+    <string name="previous_button_description" msgid="1169511027880317546">"Anterior"</string>
+    <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>
     <string name="action_edit" msgid="5882082700509010966">"Editar el archivo"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Ingresa la contraseña para desbloquear"</string>
@@ -56,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"No se pudo abrir el archivo. ¿Puede que se deba a un problema de permisos?"</string>
     <string name="page_broken" msgid="2968770793669433462">"La página no funciona para el documento PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"No hay datos suficientes para procesar el documento PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 d08f531..b1aca5f 100644
--- a/pdf/pdf-viewer/src/main/res/values-es/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-es/strings.xml
@@ -42,12 +42,9 @@
     <string name="desc_page_range" msgid="5286496438609641577">"páginas <xliff:g id="FIRST">%1$d</xliff:g> a <xliff:g id="LAST">%2$d</xliff:g> de <xliff:g id="TOTAL">%3$d</xliff:g>"</string>
     <string name="desc_image_alt_text" msgid="7700601988820586333">"Imagen: <xliff:g id="ALT_TEXT">%1$s</xliff:g>"</string>
     <string name="hint_find" msgid="5385388836603550565">"Buscar en el archivo"</string>
-    <!-- no translation found for previous_button_description (1169511027880317546) -->
-    <skip />
-    <!-- no translation found for next_button_description (4702699322249103693) -->
-    <skip />
-    <!-- no translation found for close_button_description (7379823906921067675) -->
-    <skip />
+    <string name="previous_button_description" msgid="1169511027880317546">"Anterior"</string>
+    <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>
     <string name="action_edit" msgid="5882082700509010966">"Editar archivo"</string>
     <string name="password_not_entered" msgid="8875370870743585303">"Introduce la contraseña para desbloquear"</string>
@@ -56,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"No se ha podido abrir el archivo. ¿Puede que se deba a un problema de permisos?"</string>
     <string name="page_broken" msgid="2968770793669433462">"La página no funciona para el documento PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Datos insuficientes para procesar el documento PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 902cdd0..d640ef5 100644
--- a/pdf/pdf-viewer/src/main/res/values-et/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-et/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Faili avamine nurjus. Probleem võib olla seotud lubadega."</string>
     <string name="page_broken" msgid="2968770793669433462">"Rikutud leht PDF-dokumendis"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF-dokumendi töötlemiseks pole piisavalt andmeid"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 239b72c..20770aa 100644
--- a/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Ezin izan da ireki fitxategia. Agian ez duzu horretarako baimenik?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF dokumentuaren orria hondatuta dago"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Ez dago behar adina daturik PDF dokumentua prozesatzeko"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 42aa1cd..0669b17 100644
--- a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"فایل باز نشد. احتمالاً مشکلی در اجازه وجود دارد؟"</string>
     <string name="page_broken" msgid="2968770793669433462">"‏صفحه سند PDF خراب است"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"‏داده‌ها برای پردازش سند PDF کافی نیست"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 cdce79c..3518c19 100644
--- a/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Tiedoston avaaminen epäonnistui. Mahdollinen lupaan liittyvä ongelma?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF-dokumenttiin liittyvä sivu on rikki"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Riittämätön data PDF-dokumentin käsittelyyn"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 453aacf..8a25992 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Échec de l\'ouverture du fichier. Problème d\'autorisation éventuel?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Page brisée pour le document PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Données insuffisantes pour le traitement du document PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 cffc34d..dd5fcad 100644
--- a/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Échec de l\'ouverture du fichier. Problème d\'autorisation possible ?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Page non fonctionnelle pour le document PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Données insuffisantes pour le traitement du document PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 67960e4..ebe0816 100644
--- a/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Produciuse un erro ao abrir o ficheiro. É posible que haxa problemas co permiso?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Non funciona a páxina para o documento PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Os datos non son suficientes para procesar o documento PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 f0fe5ae..ae95929 100644
--- a/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ફાઇલ ખોલવામાં નિષ્ફળ રહ્યાં. શું તમારી પાસે આની પરવાનગી નથી?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF દસ્તાવેજ માટે પેજ લોડ થઈ રહ્યું નથી"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF દસ્તાવેજ પર પ્રક્રિયા કરવા માટે પર્યાપ્ત ડેટા નથી"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 d1fe782..49f8c1d 100644
--- a/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"फ़ाइल नहीं खोली जा सकी. क्या आपके पास इसकी अनुमति नहीं है?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF दस्तावेज़ के लिए पेज लोड नहीं हो रहा है"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF दस्तावेज़ को प्रोसेस करने के लिए, ज़रूरत के मुताबिक डेटा नहीं है"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"PDF फ़ाइल नहीं खोली जा सकी"</string>
 </resources>
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 4605373..7248c6ee 100644
--- a/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Otvaranje datoteke nije uspjelo. Možda postoji problem s dopuštenjem?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Stranica je raščlanjena za PDF dokument"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nema dovoljno podataka za obradu PDF dokumenta"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 a733547..f63a921 100644
--- a/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Nem sikerült megnyitni a fájlt. Engedéllyel kapcsolatos problémáról lehet szó?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Az oldal nem tölt be a PDF-dokumentumban"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nem áll rendelkezésre elegendő adat a PDF-dokumentum feldolgozásához"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 901715c..71d24c2 100644
--- a/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Չհաջողվեց բացել ֆայլը։ Գուցե թույլտվության հետ կապված խնդի՞ր է։"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF փաստաթղթի էջը վնասված է"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Ոչ բավարար տվյալներ PDF փաստաթղթի մշակման համար"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 fa9c752..3c9e624 100644
--- a/pdf/pdf-viewer/src/main/res/values-in/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-in/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Gagal membuka file. Kemungkinan masalah izin?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Halaman dokumen PDF rusak"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Data tidak cukup untuk memproses dokumen PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 9716ab1..9378e05 100644
--- a/pdf/pdf-viewer/src/main/res/values-is/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-is/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Ekki tókst að opna skrána. Hugsanlega vandamál tengt heimildum?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Síða í PDF-skjali er gölluð"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Ekki næg gögn fyrir úrvinnslu á PDF-skjali"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 564eecd..89a8d17 100644
--- a/pdf/pdf-viewer/src/main/res/values-it/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-it/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Impossibile aprire il file. Possibile problema di autorizzazione?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Pagina inaccessibile per il documento PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Dati insufficienti per l\'elaborazione del documento PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 6ce9431..3dfd510 100644
--- a/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"לא ניתן לפתוח את הקובץ. יכול להיות שיש בעיה בהרשאה."</string>
     <string name="page_broken" msgid="2968770793669433462">"‏קישור מנותק בדף למסמך ה-PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"‏אין מספיק נתונים כדי לעבד את מסמך ה-PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 f03d62a..a48cc46 100644
--- a/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"ファイルを開けませんでした。権限に問題がある可能性はありませんか?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ドキュメントのページが壊れています"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"データ不足のため PDF ドキュメントを処理できません"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"PDF ファイルを開けません"</string>
 </resources>
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 864fd74..3fd5c9b 100644
--- a/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"ფაილის გახსნა ვერ მოხერხდა. შესაძლოა ნებართვის პრობლემა იყოს?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF დოკუმენტის გვერდი დაზიანებულია"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"მონაცემები არ არის საკმარისი PDF დოკუმენტის დასამუშავებლად"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"PDF ფაილის გახსნა ვერ ხერხდება"</string>
 </resources>
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 b94ea34..5846202 100644
--- a/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Файл ашылмады. Бәлкім, рұқсатқа қатысты бір мәселе бар?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF құжатының беті бұзылған."</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF құжатын өңдеу үшін деректер жеткіліксіз."</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 03a0ebd..931c43f 100644
--- a/pdf/pdf-viewer/src/main/res/values-km/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-km/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"មិនអាច​បើក​ឯកសារនេះ​បានទេ។ អាចមាន​បញ្ហា​នៃ​ការអនុញ្ញាតឬ?"</string>
     <string name="page_broken" msgid="2968770793669433462">"ទំព័រ​មិនដំណើរការ​សម្រាប់​ឯកសារ PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"មានទិន្នន័យ​មិនគ្រប់គ្រាន់​សម្រាប់​ដំណើរការ​ឯកសារ PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 4c114f7..fb8b009 100644
--- a/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ಫೈಲ್ ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ. ಸಂಭವನೀಯ ಅನುಮತಿ ಸಮಸ್ಯೆ?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ಡಾಕ್ಯುಮೆಂಟ್‌ಗೆ ಸಂಬಂಧಿಸಿದ ಪುಟ ಮುರಿದಿದೆ"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ಡಾಕ್ಯುಮೆಂಟ್ ಅನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಕಷ್ಟು ಡೇಟಾ ಇಲ್ಲ"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 54655ec..9530691 100644
--- a/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"파일을 열 수 없습니다. 권한 문제가 있을 수 있나요?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF 문서의 페이지가 손상되었습니다."</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF 문서 처리를 위한 데이터가 부족합니다."</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 90e6450..92e5119 100644
--- a/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Файл ачылган жок. Керектүү уруксаттар жок окшойт."</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF документинин барагы бузук"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF документин иштетүү үчүн маалымат жетишсиз"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 895280e..baa1c28 100644
--- a/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ເປີດໄຟລ໌ບໍ່ສຳເລັດ. ອາດເປັນຍ້ອນບັນຫາທາງການອະນຸຍາດບໍ?"</string>
     <string name="page_broken" msgid="2968770793669433462">"ໜ້າເສຍຫາຍສໍາລັບເອກະສານ PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"ຂໍ້ມູນບໍ່ພຽງພໍສໍາລັບການປະມວນຜົນເອກະສານ PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 8b14e98..588ff87 100644
--- a/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Nepavyko atidaryti failo. Galima su leidimais susijusi problema?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Sugadintas PDF dokumento puslapis"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nepakanka duomenų PDF dokumentui apdoroti"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 22e20c9..738615d 100644
--- a/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Neizdevās atvērt failu. Iespējams, ir radusies problēma ar atļaujām."</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF dokumenta lapa ir bojāta"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nepietiekams datu apjoms, lai apstrādātu PDF dokumentu"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 cce9ac3..e6b85c2 100644
--- a/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Не можеше да се отвори датотеката. Можеби има проблем со дозволата?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Страницата не може да го вчита PDF-документот"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Недоволно податоци за обработка на PDF-документот"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 b07acaa..760a696 100644
--- a/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ഫയൽ തുറക്കാനായില്ല. അനുമതി സംബന്ധിച്ച പ്രശ്‌നമാകാൻ സാധ്യതയുണ്ടോ?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ഡോക്യുമെന്റിനായി പേജ് ലോഡ് ചെയ്യാനായില്ല"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ഡോക്യുമെന്റ് പ്രോസസ് ചെയ്യാൻ മതിയായ ഡാറ്റയില്ല"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 756390b..9c8f052 100644
--- a/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Файлыг нээж чадсангүй. Зөвшөөрөлтэй холбоотой асуудал байж болох уу?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF баримт бичгийн хуудас эвдэрсэн"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF баримт бичгийг боловсруулахад өгөгдөл хангалтгүй байна"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 a6d1c6e..40ee1a8 100644
--- a/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"फाइल उघडता आली नाही. परवानगीशी संबंधित संभाव्य समस्या?"</string>
     <string name="page_broken" msgid="2968770793669433462">"पीडीएफ दस्तऐवजासाठी पेज खंडित झाले आहे"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF दस्तऐवजावर प्रक्रिया करण्यासाठी डेटा पुरेसा नाही"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 acf0ee8..f905244 100644
--- a/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Gagal membuka fail. Kemungkinan terdapat masalah berkaitan dengan kebenaran?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Halaman rosak untuk dokumen PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Data tidak mencukupi untuk memproses dokumen PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 bd311a7..c288df3 100644
--- a/pdf/pdf-viewer/src/main/res/values-my/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-my/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ဖိုင်ကို ဖွင့်၍မရလိုက်ပါ။ ခွင့်ပြုချက် ပြဿနာ ဖြစ်နိုင်လား။"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF မှတ်တမ်းအတွက် စာမျက်နှာ ပျက်နေသည်"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF မှတ်တမ်း လုပ်ဆောင်ရန်အတွက် ဒေတာ မလုံလောက်ပါ"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 23107ac..06e5547 100644
--- a/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Kunne ikke åpne filen. Kan det være et problem med tillatelser?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Siden er ødelagt for PDF-dokumentet"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Det er utilstrekkelige data for behandling av PDF-dokumentet"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 da53207..d847ed0c 100644
--- a/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"फाइल खोल्न सकिएन। तपाईंसँग यो फाइल खोल्ने अनुमति छैन?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF डकुमेन्टको पेज लोड गर्न सकिएन"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF डकुमेन्ट प्रोसेस गर्न पर्याप्त जानकारी छैन"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
diff --git a/pdf/pdf-viewer/src/main/res/values-night/colors.xml b/pdf/pdf-viewer/src/main/res/values-night/colors.xml
index ce96df2..ea1e693 100644
--- a/pdf/pdf-viewer/src/main/res/values-night/colors.xml
+++ b/pdf/pdf-viewer/src/main/res/values-night/colors.xml
@@ -17,5 +17,5 @@
 <resources>
     <color name="pdf_viewer_color_primary">@color/m3_sys_color_dark_primary</color>
     <color name="pdf_viewer_color_on_surface">@color/m3_sys_color_dark_on_surface</color>
-    <color name="pdf_viewer_color_on_error">@color/m3_sys_color_dark_on_error</color>
+    <color name="pdf_viewer_color_error">@color/m3_sys_color_dark_error</color>
 </resources>
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 9ad4b40..5ceea0c 100644
--- a/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Kan het bestand niet openen. Mogelijk rechtenprobleem?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Pagina van het pdf-document kan niet worden geladen"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Onvoldoende gegevens om het pdf-document te verwerken"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 cf3e282..66b7f68 100644
--- a/pdf/pdf-viewer/src/main/res/values-or/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-or/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ଫାଇଲ ଖୋଲିବାରେ ବିଫଳ ହୋଇଛି। ସମ୍ଭାବ୍ୟ ଅନୁମତି ସମସ୍ୟା ଅଛି?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ଡକ୍ୟୁମେଣ୍ଟ ପାଇଁ ପୃଷ୍ଠା ବିଭାଜିତ ହୋଇଛି"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ଡକ୍ୟୁମେଣ୍ଟ ପ୍ରକ୍ରିୟାକରଣ ପାଇଁ ପର୍ଯ୍ୟାପ୍ତ ଡାଟା ନାହିଁ"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 86a73eb..8d4c105 100644
--- a/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ਫ਼ਾਈਲ ਨੂੰ ਖੋਲ੍ਹਣਾ ਅਸਫਲ ਰਿਹਾ। ਕੀ ਸੰਭਵ ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਸਮੱਸਿਆ ਹੈ?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ਦਸਤਾਵੇਜ਼ ਲਈ ਪੰਨਾ ਲੋਡ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ਦਸਤਾਵੇਜ਼ \'ਤੇ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਲਈ ਲੋੜੀਂਦਾ ਡਾਟਾ ਨਹੀਂ ਹੈ"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 ce974f6..6583cb5 100644
--- a/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Nie udało się otworzyć pliku. Może to przez problem z uprawnieniami?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Strona w dokumencie PDF jest uszkodzona"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Brak wystarczającej ilości danych do przetworzenia dokumentu PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 f3fdf6c..e8beb95 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Falha ao abrir o arquivo. Possível problema de permissão?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Página do documento PDF corrompida"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Dados insuficientes para processamento do documento PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 ff10bc1..2a1a80a 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
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"Falha ao abrir o ficheiro. Possível problema de autorização?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Página danificada para o documento PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Dados insuficientes para processar o documento PDF"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"Não é possível abrir o ficheiro PDF"</string>
 </resources>
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 f3fdf6c..e8beb95 100644
--- a/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Falha ao abrir o arquivo. Possível problema de permissão?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Página do documento PDF corrompida"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Dados insuficientes para processamento do documento PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 669086d..ef6b73d 100644
--- a/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Nu s-a putut deschide fișierul. Există vreo problemă cu permisiunile?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Pagină deteriorată pentru documentul PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Date insuficiente pentru procesarea documentului PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 d7163f2..665e7cb 100644
--- a/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Не удалось открыть файл. Возможно, нет необходимых разрешений."</string>
     <string name="page_broken" msgid="2968770793669433462">"Страница документа PDF повреждена"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Недостаточно данных для обработки документа PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 bba16c5..dc5d075 100644
--- a/pdf/pdf-viewer/src/main/res/values-si/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-si/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ගොනුව විවෘත කිරීමට අසමත් විය. අවසර ගැටලුවක් විය හැකි ද?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ලේඛනය සඳහා පිටුව හානි වී ඇත"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ලේඛනය සැකසීම සඳහා ප්‍රමාණවත් දත්ත නොමැත"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 f8f3997..d44c7b6 100644
--- a/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Súbor sa nepodarilo otvoriť. Možno sa vyskytol problém s povolením."</string>
     <string name="page_broken" msgid="2968770793669433462">"Stránka sa v dokumente vo formáte PDF nedá načítať"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"V dokumente vo formáte PDF nie je dostatok údajov na spracovanie"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 ad7b4cd..afef99a 100644
--- a/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"Odpiranje datoteke ni uspelo. Ali morda gre za težavo z dovoljenjem?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Strani iz dokumenta PDF ni mogoče prikazati"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Nezadostni podatki za obdelavo dokumenta PDF"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"Datoteke PDF ni mogoče odpreti"</string>
 </resources>
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 0e775ba..37347d3 100644
--- a/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Hapja e skedarit dështoi. Problem i mundshëm me lejet?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Faqe e dëmtuar për dokumentin PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Të dhëna të pamjaftueshme për përpunimin e dokumentit PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 d70749c..bcab510 100644
--- a/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Отварање фајла није успело. Можда постоје проблеми са дозволом?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Неисправна страница за PDF документ"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Недовољно података за обраду PDF документа"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 eae0c6a..3fa349f 100644
--- a/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Det gick inte att öppna filen. Detta kan bero på ett behörighetsproblem."</string>
     <string name="page_broken" msgid="2968770793669433462">"Det gick inte att läsa in en sida i PDF-dokumentet"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Otillräcklig data för att behandla PDF-dokumentet"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 e976caf..abf9c4b5 100644
--- a/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Imeshindwa kufungua faili. Je, linaweza kuwa tatizo la ruhusa?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Ukurasa wa hati ya PDF una tatizo"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Hamna data ya kutosha kuchakata hati ya PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 8a51fa4..2d1d291 100644
--- a/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"ஃபைலைத் திறக்க முடியவில்லை. அனுமதி தொடர்பான சிக்கல் உள்ளதா?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF ஆவணத்தை ஏற்ற முடியவில்லை"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF ஆவணத்தைச் செயலாக்குவதற்குப் போதுமான தரவு இல்லை"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 e5ff775..ffcee7a 100644
--- a/pdf/pdf-viewer/src/main/res/values-te/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-te/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"ఫైల్‌ను తెరవడం విఫలమైంది. అనుమతికి సంబంధించిన సమస్య కావచ్చా?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF డాక్యుమెంట్‌కు సంబంధించి పేజీ బ్రేక్ అయింది"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF డాక్యుమెంట్‌ను ప్రాసెస్ చేయడానికి డేటా తగినంత లేదు"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"PDF ఫైల్‌ను తెరవడం సాధ్యపడదు"</string>
 </resources>
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 971e3e2..be31750 100644
--- a/pdf/pdf-viewer/src/main/res/values-th/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-th/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"เปิดไฟล์ไม่สำเร็จ อาจเกิดจากปัญหาด้านสิทธิ์"</string>
     <string name="page_broken" msgid="2968770793669433462">"หน้าในเอกสาร PDF เสียหาย"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"ข้อมูลไม่เพียงพอสำหรับการประมวลผลเอกสาร PDF"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"เปิดไฟล์ PDF ไม่ได้"</string>
 </resources>
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 be6d695..5b20647 100644
--- a/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"Hindi nabuksan ang file. Baka may isyu sa pahintulot?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Sira ang page para sa PDF na dokumento"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Kulang ang data para maproseso ang PDF na dokumento"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"Hindi mabuksan ang PDF file"</string>
 </resources>
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 09803ed..8ad6bf2 100644
--- a/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Dosya açılamadı. İzin sorunundan kaynaklanıyor olabilir mi?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF dokümanının sayfası bozuk"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF dokümanını işleyecek kadar yeterli veri yok"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 fc81a4b..c381f20 100644
--- a/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Не вдалося відкрити файл. Можливо, виникла проблема з дозволом."</string>
     <string name="page_broken" msgid="2968770793669433462">"Сторінку документа PDF пошкоджено"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Недостатньо даних для обробки документа PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 e733c19..6027e36 100644
--- a/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"فائل کھولنے میں ناکام۔ کیا یہ اجازت کا مسئلہ ہو سکتا ہے؟"</string>
     <string name="page_broken" msgid="2968770793669433462">"‏‫PDF دستاویز کیلئے شکستہ صفحہ"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"‏‫PDF دستاویز پر کارروائی کرنے کیلئے ڈیٹا ناکافی ہے"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 54c3148..41b89f8 100644
--- a/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"Fayl ochilmadi. Ruxsat bilan muammo bormi?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF hujjat sahifasi yaroqsiz"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"PDF hujjatni qayta ishlash uchun kerakli axborotlar yetarli emas"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"PDF fayk ochilmadi"</string>
 </resources>
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 c2015bc..5f50634 100644
--- a/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Không mở được tệp này. Có thể là do vấn đề về quyền?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Tài liệu PDF này bị lỗi trang"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Không đủ dữ liệu để xử lý tài liệu PDF này"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 4abd99c..c6dbf7e 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
@@ -53,4 +53,5 @@
     <string name="file_error" msgid="4003885928556884091">"无法打开文件。可能是由于权限问题导致?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF 文档的页面已损坏"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"数据不足,无法处理 PDF 文档"</string>
+    <string name="error_cannot_open_pdf" msgid="2361919778558145071">"无法打开 PDF 文件"</string>
 </resources>
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 3510530..691bdfe 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"無法開啟檔案。可能有權限問題?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF 文件頁面已損毀"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"沒有足夠資料處理 PDF 文件"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 10fd054..b2be3f4 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
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"無法開啟檔案。有可能是權限問題?"</string>
     <string name="page_broken" msgid="2968770793669433462">"PDF 文件的頁面損毀"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"資料不足,無法處理 PDF 文件"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
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 4065bd2..ba456e5 100644
--- a/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
@@ -53,4 +53,6 @@
     <string name="file_error" msgid="4003885928556884091">"Yehlulekile ukuvula ifayela. Inkinga yemvume engaba khona?"</string>
     <string name="page_broken" msgid="2968770793669433462">"Ikhasi eliphuliwe ledokhumenti ye-PDF"</string>
     <string name="needs_more_data" msgid="3520133467908240802">"Idatha enganele yokucubungula idokhumenti ye-PDF"</string>
+    <!-- no translation found for error_cannot_open_pdf (2361919778558145071) -->
+    <skip />
 </resources>
diff --git a/pdf/pdf-viewer/src/main/res/values/colors.xml b/pdf/pdf-viewer/src/main/res/values/colors.xml
index 63ae166..8730c12 100644
--- a/pdf/pdf-viewer/src/main/res/values/colors.xml
+++ b/pdf/pdf-viewer/src/main/res/values/colors.xml
@@ -17,7 +17,7 @@
 <resources>
     <color name="pdf_viewer_color_primary">@color/m3_sys_color_light_primary</color>
     <color name="pdf_viewer_color_on_surface">@color/m3_sys_color_light_on_surface</color>
-    <color name="pdf_viewer_color_on_error">@color/m3_sys_color_light_on_error</color>
+    <color name="pdf_viewer_color_error">@color/m3_sys_color_light_error</color>
     <!-- m3_sys_color_primary_fixed_dim doesn't have a day/night version, therefore defined only once -->
     <color name="pdf_viewer_selection_handles">@color/m3_sys_color_primary_fixed_dim</color>
 </resources>
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PaginationModelTest.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PaginationModelTest.java
index eecca89..a568c6f 100644
--- a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PaginationModelTest.java
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PaginationModelTest.java
@@ -178,25 +178,25 @@
         mPaginationModel.addPage(1, mdDimensions);
         mPaginationModel.addPage(2, lgDimensions);
         // Setting viewArea large enough to accommodate the entire model.
-        mPaginationModel.setViewArea(new Rect(0, 0, 800, 800));
+        Rect viewArea = new Rect(0, 0, 800, 800);
 
         Rect expectedSmLocation = new Rect(300, 0, 500, 100);
-        assertThat(mPaginationModel.getPageLocation(0)).isEqualTo(expectedSmLocation);
+        assertThat(mPaginationModel.getPageLocation(0, viewArea)).isEqualTo(expectedSmLocation);
 
         Rect expectedMdLocation =
                 new Rect(200, 100 + getSpacingAbovePage(1), 600, 300 + getSpacingAbovePage(1));
-        assertThat(mPaginationModel.getPageLocation(1)).isEqualTo(expectedMdLocation);
+        assertThat(mPaginationModel.getPageLocation(1, viewArea)).isEqualTo(expectedMdLocation);
 
         Rect expectedLgLocation =
                 new Rect(0, 300 + getSpacingAbovePage(2), 800, 700 + getSpacingAbovePage(2));
-        Assert.assertEquals(expectedLgLocation, mPaginationModel.getPageLocation(2));
-        assertThat(mPaginationModel.getPageLocation(2)).isEqualTo(expectedLgLocation);
+        assertThat(mPaginationModel.getPageLocation(2, viewArea)).isEqualTo(expectedLgLocation);
     }
 
     /**
-     * {@link PaginationModel#getPageLocation(int)} should try to fit as much of each page into the
-     * viewable area as possible. Dimensions do not change vertically but pages that are smaller
-     * than {@link PaginationModel#getWidth()} can be moved horizontally to make this happen.
+     * {@link PaginationModel#getPageLocation(int, Rect)} should try to fit as much of each page
+     * into the viewable area as possible. Dimensions do not change vertically but pages that are
+     * smaller than {@link PaginationModel#getWidth()} can be moved horizontally to make this
+     * happen.
      *
      * <p>Page 1's width is smaller than {@link PaginationModel#getWidth()} so it will be placed in
      * the middle when the visible area covers the whole model {@see #testGetPageLocation}. When the
@@ -216,11 +216,11 @@
         mPaginationModel.addPage(2, lgDimensions);
 
         // Setting viewArea to a 300x200 section in the bottom-left corner of the model.
-        mPaginationModel.setViewArea(new Rect(0, 500, 200, 800));
+        Rect viewArea = new Rect(0, 500, 200, 800);
 
         Rect expectedMdLocation =
                 new Rect(0, 100 + getSpacingAbovePage(1), 400, 300 + getSpacingAbovePage(1));
-        assertThat(mPaginationModel.getPageLocation(1)).isEqualTo(expectedMdLocation);
+        assertThat(mPaginationModel.getPageLocation(1, viewArea)).isEqualTo(expectedMdLocation);
     }
 
     /**
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/ZoomScrollValueObserverTest.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/ZoomScrollValueObserverTest.java
index b19e190..93e2b09 100644
--- a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/ZoomScrollValueObserverTest.java
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/ZoomScrollValueObserverTest.java
@@ -80,7 +80,7 @@
         mNewPosition = new ZoomView.ZoomScroll(1.0f, 0, 0, false);
 
         when(mMockPaginatedView.getPageRangeHandler()).thenReturn(mPageRangeHandler);
-        when(mMockPaginatedView.getPaginationModel()).thenReturn(mMockPaginationModel);
+        when(mMockPaginatedView.getModel()).thenReturn(mMockPaginationModel);
         when(mMockPaginationModel.isInitialized()).thenReturn(true);
         when(mMockZoomView.getHeight()).thenReturn(100);
         when(mPageRangeHandler.computeVisibleRange(0, 1.0f, 100, false)).thenReturn(PAGE_RANGE);
@@ -103,7 +103,7 @@
         zoomScrollValueObserver.onChange(OLD_POSITION, mNewPosition);
 
         verify(mMockZoomView).setStableZoom(1.0f);
-        verify(mMockPaginationModel).setViewArea(RECT);
+        verify(mMockPaginatedView).setViewArea(RECT);
         verify(mMockPaginatedView).refreshPageRangeInVisibleArea(mNewPosition, 100);
         verify(mMockPaginatedView).handleGonePages(false);
         verify(mMockPaginatedView).loadInvisibleNearPageRange(1.0f);
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/VersionCompatUtil.kt b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/VersionCompatUtil.kt
index e685b4c..ef1a4b4 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/VersionCompatUtil.kt
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/VersionCompatUtil.kt
@@ -32,25 +32,9 @@
             SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S) >= minVersion
     }
 
-    fun isRWithMinExtServicesVersion(minVersion: Int): Boolean {
-        return Build.VERSION.SDK_INT == 30 &&
-            SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= minVersion
-    }
-
     // Helper method to determine if version is testable, for APIs that are S+ only
     fun isTestableVersion(minAdServicesVersion: Int, minExtServicesVersion: Int): Boolean {
         return isTPlusWithMinAdServicesVersion(minAdServicesVersion) ||
             isSWithMinExtServicesVersion(minExtServicesVersion)
     }
-
-    // Helper method to determine if version is testable, for APIs that are available on R
-    fun isTestableVersion(
-        minAdServicesVersion: Int,
-        minExtServicesVersionS: Int,
-        minExtServicesVersionR: Int
-    ): Boolean {
-        return isTPlusWithMinAdServicesVersion(minAdServicesVersion) ||
-            isSWithMinExtServicesVersion(minExtServicesVersionS) ||
-            isRWithMinExtServicesVersion(minExtServicesVersionR)
-    }
 }
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/adid/AdIdManagerFuturesTest.kt b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/adid/AdIdManagerFuturesTest.kt
index dcf44e7d..3b2c545 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/adid/AdIdManagerFuturesTest.kt
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/adid/AdIdManagerFuturesTest.kt
@@ -17,7 +17,6 @@
 package androidx.privacysandbox.ads.adservices.java.adid
 
 import android.adservices.adid.AdIdManager
-import android.adservices.common.AdServicesOutcomeReceiver
 import android.content.Context
 import android.os.Looper
 import android.os.OutcomeReceiver
@@ -54,14 +53,12 @@
     private var mSession: StaticMockitoSession? = null
     private val mValidAdExtServicesSdkExtVersionS =
         VersionCompatUtil.isSWithMinExtServicesVersion(9)
-    private val mValidAdExtServicesSdkExtVersionR =
-        VersionCompatUtil.isRWithMinExtServicesVersion(11)
 
     @Before
     fun setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext<Context>())
 
-        if (mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR) {
+        if (mValidAdExtServicesSdkExtVersionS) {
             // setup a mockitoSession to return the mocked manager
             // when the static method .get() is called
             mSession =
@@ -78,11 +75,10 @@
     @SdkSuppress(maxSdkVersion = 33, minSdkVersion = 30)
     fun testAdIdOlderVersions() {
         Assume.assumeFalse(
-            "maxSdkVersion = API 33 ext 3 or API 31/32 ext 8 or API 30 ext 10",
+            "maxSdkVersion = API 33 ext 3 or API 31/32 ext 8",
             VersionCompatUtil.isTestableVersion(
                 /* minAdServicesVersion=*/ 4,
                 /* minExtServicesVersionS=*/ 9,
-                /* minExtServicesVersionR=*/ 11
             )
         )
         Truth.assertThat(AdIdManagerFutures.from(mContext)).isEqualTo(null)
@@ -91,24 +87,15 @@
     @Test
     fun testAdIdAsync() {
         Assume.assumeTrue(
-            "minSdkVersion = API 33 ext 4 or API 31/32 ext 9 or API 30 ext 11",
+            "minSdkVersion = API 33 ext 4 or API 31/32 ext 9",
             VersionCompatUtil.isTestableVersion(
                 /* minAdServicesVersion= */ 4,
                 /* minExtServicesVersionS=*/ 9,
-                /* minExtServicesVersionR=*/ 11
             )
         )
 
-        val adIdManager =
-            mockAdIdManager(
-                mContext,
-                mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR
-            )
-
-        when (mValidAdExtServicesSdkExtVersionR) {
-            true -> setupResponseR(adIdManager)
-            false -> setupResponseSPlus(adIdManager)
-        }
+        val adIdManager = mockAdIdManager(mContext, mValidAdExtServicesSdkExtVersionS)
+        setupResponseSPlus(adIdManager)
 
         val managerCompat = AdIdManagerFutures.from(mContext)
 
@@ -117,11 +104,7 @@
 
         // Verify that the result of the compat call is correct.
         verifyResponse(result.get())
-
-        when (mValidAdExtServicesSdkExtVersionR) {
-            true -> verifyOnR(adIdManager)
-            false -> verifyOnSPlus(adIdManager)
-        }
+        verifyOnSPlus(adIdManager)
     }
 
     @SdkSuppress(minSdkVersion = 30)
@@ -157,37 +140,6 @@
                 )
         }
 
-        private fun setupResponseR(adIdManager: AdIdManager) {
-            // Set up the response that AdIdManager will return when the compat code calls it.
-            val adId = android.adservices.adid.AdId("1234", false)
-            val answer = { args: InvocationOnMock ->
-                assertNotEquals(Looper.getMainLooper(), Looper.myLooper())
-                val receiver =
-                    args.getArgument<
-                        AdServicesOutcomeReceiver<android.adservices.adid.AdId, Exception>
-                    >(
-                        1
-                    )
-                receiver.onResult(adId)
-                null
-            }
-            Mockito.doAnswer(answer)
-                .`when`(adIdManager)
-                .getAdId(
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<android.adservices.adid.AdId, Exception>>()
-                )
-        }
-
-        private fun verifyOnR(adIdManager: AdIdManager) {
-            // Verify that the compat code was invoked correctly.
-            Mockito.verify(adIdManager)
-                .getAdId(
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<android.adservices.adid.AdId, Exception>>()
-                )
-        }
-
         private fun verifyOnSPlus(adIdManager: AdIdManager) {
             // Verify that the compat code was invoked correctly.
             Mockito.verify(adIdManager)
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
index 8eea312..2df8a7a 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
@@ -115,17 +115,6 @@
         }
     }
 
-    public void enableBackCompatOnR() {
-        runShellCommand("device_config put adservices adservice_enabled true");
-        runShellCommand("device_config put adservices enable_back_compat true");
-    }
-
-
-    public void disableBackCompatOnR() {
-        runShellCommand("device_config put adservices adservice_enabled false");
-        runShellCommand("device_config put adservices enable_back_compat false");
-    }
-
     public void enableBackCompatOnS() {
         runShellCommand("device_config put adservices enable_back_compat true");
         runShellCommand("device_config put adservices consent_source_of_truth 3");
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/adid/AdIdManagerTest.java b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/adid/AdIdManagerTest.java
index dd54c93..dc17deb 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/adid/AdIdManagerTest.java
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/adid/AdIdManagerTest.java
@@ -80,8 +80,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 4,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         AdIdManagerFutures adIdManager =
                 AdIdManagerFutures.from(ApplicationProvider.getApplicationContext());
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/measurement/MeasurementManagerTest.java b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/measurement/MeasurementManagerTest.java
index fc16065..7f45668 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/measurement/MeasurementManagerTest.java
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/measurement/MeasurementManagerTest.java
@@ -96,8 +96,6 @@
                 MeasurementManagerFutures.from(ApplicationProvider.getApplicationContext());
         if (VersionCompatUtil.INSTANCE.isSWithMinExtServicesVersion(9)) {
             mTestUtil.enableBackCompatOnS();
-        } else if (VersionCompatUtil.INSTANCE.isRWithMinExtServicesVersion(11)) {
-            mTestUtil.enableBackCompatOnR();
         }
 
         // Put in a short sleep to make sure the updated config propagates
@@ -115,8 +113,6 @@
         mTestUtil.overrideDisableMeasurementEnrollmentCheck("0");
         if (VersionCompatUtil.INSTANCE.isSWithMinExtServicesVersion(9)) {
             mTestUtil.disableBackCompatOnS();
-        } else if (VersionCompatUtil.INSTANCE.isRWithMinExtServicesVersion(11)) {
-            mTestUtil.disableBackCompatOnR();
         }
 
         // Cool-off rate limiter
@@ -129,8 +125,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         assertThat(
                         mMeasurementManager
@@ -146,8 +141,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         SourceRegistrationRequest request =
                 new SourceRegistrationRequest.Builder(
@@ -162,8 +156,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         assertThat(mMeasurementManager.registerTriggerAsync(TRIGGER_REGISTRATION_URI).get())
                 .isNotNull();
@@ -175,8 +168,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         WebSourceParams webSourceParams = new WebSourceParams(SOURCE_REGISTRATION_URI, false);
 
@@ -199,8 +191,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         WebTriggerParams webTriggerParams = new WebTriggerParams(TRIGGER_REGISTRATION_URI, false);
         WebTriggerRegistrationRequest webTriggerRegistrationRequest =
@@ -236,8 +227,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         DeletionRequest deletionRequest =
                 new DeletionRequest.Builder(
@@ -258,8 +248,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         DeletionRequest deletionRequest =
                 new DeletionRequest.Builder(
@@ -283,8 +272,7 @@
         Assume.assumeTrue(
                 VersionCompatUtil.INSTANCE.isTestableVersion(
                         /* minAdServicesVersion= */ 5,
-                        /* minExtServicesVersionS= */ 9,
-                        /* minExtServicesVersionR= */ 11));
+                        /* minExtServicesVersionS= */ 9));
 
         int result = mMeasurementManager.getMeasurementApiStatusAsync().get();
         assertThat(result).isEqualTo(1);
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/measurement/MeasurementManagerFuturesTest.kt b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/measurement/MeasurementManagerFuturesTest.kt
index 363191c..eeae81f 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/measurement/MeasurementManagerFuturesTest.kt
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/measurement/MeasurementManagerFuturesTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.privacysandbox.ads.adservices.java.measurement
 
-import android.adservices.common.AdServicesOutcomeReceiver
 import android.adservices.measurement.MeasurementManager
 import android.content.Context
 import android.net.Uri
@@ -75,16 +74,12 @@
     private var mSession: StaticMockitoSession? = null
     private val mValidAdExtServicesSdkExtVersionS =
         VersionCompatUtil.isSWithMinExtServicesVersion(9)
-    private val mValidAdExtServicesSdkExtVersionR =
-        VersionCompatUtil.isRWithMinExtServicesVersion(11)
-    private val mValidExtServicesVersion =
-        mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR
 
     @Before
     fun setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext<Context>())
 
-        if (mValidExtServicesVersion) {
+        if (mValidAdExtServicesSdkExtVersionS) {
             // setup a mockitoSession to return the mocked manager
             // when the static method .get() is called
             mSession =
@@ -104,11 +99,10 @@
     @SdkSuppress(maxSdkVersion = 33, minSdkVersion = 30)
     fun testMeasurementOlderVersions() {
         Assume.assumeFalse(
-            "maxSdkVersion = API 33 ext 4 or API 31/32 ext 8 or API 30 ext 10",
+            "maxSdkVersion = API 33 ext 4 or API 31/32 ext 8",
             VersionCompatUtil.isTestableVersion(
                 /* minAdServicesVersion=*/ 5,
                 /* minExtServicesVersionS=*/ 9,
-                /* minExtServicesVersionR=*/ 11
             )
         )
         assertThat(from(mContext)).isEqualTo(null)
@@ -556,410 +550,6 @@
             )
     }
 
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testDeleteRegistrationsAsyncOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = from(mContext)
-
-        // Set up the request.
-        val answer = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            null
-        }
-        doAnswer(answer)
-            .`when`(mMeasurementManager)
-            .deleteRegistrations(
-                any<android.adservices.measurement.DeletionRequest>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, java.lang.Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        val request =
-            DeletionRequest(
-                DeletionRequest.DELETION_MODE_ALL,
-                DeletionRequest.MATCH_BEHAVIOR_DELETE,
-                Instant.now(),
-                Instant.now(),
-                listOf(uri1),
-                listOf(uri1)
-            )
-
-        managerCompat!!.deleteRegistrationsAsync(request).get()
-
-        // Verify that the compat code was invoked correctly.
-        val captor =
-            ArgumentCaptor.forClass(android.adservices.measurement.DeletionRequest::class.java)
-        verify(mMeasurementManager)
-            .deleteRegistrations(
-                captor.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, java.lang.Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        verifyDeletionRequest(captor.value)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterSourceAsyncOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val inputEvent = mock(InputEvent::class.java)
-        val managerCompat = from(mContext)
-
-        val answer = { args: InvocationOnMock ->
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(mMeasurementManager)
-            .registerSource(
-                any<Uri>(),
-                any<InputEvent>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        managerCompat!!.registerSourceAsync(uri1, inputEvent).get()
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 = ArgumentCaptor.forClass(Uri::class.java)
-        val captor2 = ArgumentCaptor.forClass(InputEvent::class.java)
-        verify(mMeasurementManager)
-            .registerSource(
-                captor1.capture(),
-                captor2.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        assertThat(captor1.value == uri1)
-        assertThat(captor2.value == inputEvent)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterTriggerAsyncOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = from(mContext)
-
-        val answer = { args: InvocationOnMock ->
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(mMeasurementManager)
-            .registerTrigger(
-                any<Uri>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        managerCompat!!.registerTriggerAsync(uri1).get()
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 = ArgumentCaptor.forClass(Uri::class.java)
-        verify(mMeasurementManager)
-            .registerTrigger(
-                captor1.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        assertThat(captor1.value == uri1)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterWebSourceAsyncOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = from(mContext)
-
-        val answer = { args: InvocationOnMock ->
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(mMeasurementManager)
-            .registerWebSource(
-                any<android.adservices.measurement.WebSourceRegistrationRequest>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        val request =
-            WebSourceRegistrationRequest.Builder(listOf(WebSourceParams(uri2, false)), uri1)
-                .setAppDestination(appDestination)
-                .build()
-
-        // Actually invoke the compat code.
-        managerCompat!!.registerWebSourceAsync(request).get()
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 =
-            ArgumentCaptor.forClass(
-                android.adservices.measurement.WebSourceRegistrationRequest::class.java
-            )
-        verify(mMeasurementManager)
-            .registerWebSource(
-                captor1.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        val actualRequest = captor1.value
-        assertThat(actualRequest.topOriginUri == uri1)
-        assertThat(actualRequest.sourceParams.size == 1)
-        assertThat(actualRequest.appDestination == appDestination)
-        assertThat(actualRequest.sourceParams[0].registrationUri == uri2)
-        assertThat(!actualRequest.sourceParams[0].isDebugKeyAllowed)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterWebTriggerAsyncOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = from(mContext)
-
-        val answer = { args: InvocationOnMock ->
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(mMeasurementManager)
-            .registerWebTrigger(
-                any<android.adservices.measurement.WebTriggerRegistrationRequest>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        val request = WebTriggerRegistrationRequest(listOf(WebTriggerParams(uri1, false)), uri2)
-
-        // Actually invoke the compat code.
-        managerCompat!!.registerWebTriggerAsync(request).get()
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 =
-            ArgumentCaptor.forClass(
-                android.adservices.measurement.WebTriggerRegistrationRequest::class.java
-            )
-        verify(mMeasurementManager)
-            .registerWebTrigger(
-                captor1.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        val actualRequest = captor1.value
-        assertThat(actualRequest.destination == uri2)
-        assertThat(actualRequest.triggerParams.size == 1)
-        assertThat(actualRequest.triggerParams[0].registrationUri == uri1)
-        assertThat(!actualRequest.triggerParams[0].isDebugKeyAllowed)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testMeasurementApiStatusAsyncOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = from(mContext)
-
-        val state = MeasurementManager.MEASUREMENT_API_STATE_DISABLED
-        val answer = { args: InvocationOnMock ->
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Int, Exception>>(1)
-            receiver.onResult(state)
-            null
-        }
-        doAnswer(answer)
-            .`when`(mMeasurementManager)
-            .getMeasurementApiStatus(
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Int, Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        val result = managerCompat!!.getMeasurementApiStatusAsync()
-        result.get()
-
-        // Verify that the compat code was invoked correctly.
-        verify(mMeasurementManager)
-            .getMeasurementApiStatus(
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Int, Exception>>()
-            )
-
-        // Verify that the result.
-        assertThat(result.get() == state)
-    }
-
-    @ExperimentalFeatures.RegisterSourceOptIn
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterSourceAsync_allSuccessOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val inputEvent = mock(InputEvent::class.java)
-        val managerCompat = from(mContext)
-
-        val successCallback = { args: InvocationOnMock ->
-            assertNotEquals(Looper.myLooper(), Looper.getMainLooper())
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(successCallback)
-            .`when`(mMeasurementManager)
-            .registerSource(
-                any<Uri>(),
-                any<InputEvent>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        val request =
-            SourceRegistrationRequest.Builder(listOf(uri1, uri2)).setInputEvent(inputEvent).build()
-        managerCompat!!.registerSourceAsync(request).get()
-
-        // Verify that the compat code was invoked correctly.
-        verify(mMeasurementManager)
-            .registerSource(
-                eq(uri1),
-                eq(inputEvent),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-        verify(mMeasurementManager)
-            .registerSource(
-                eq(uri2),
-                eq(inputEvent),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-    }
-
-    @ExperimentalFeatures.RegisterSourceOptIn
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterSource_15thOf20Fails_atLeast15thExecutesOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val mMeasurementManager =
-            mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val mockInputEvent = mock(InputEvent::class.java)
-        val managerCompat = from(mContext)
-
-        val successCallback = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onResult(Object())
-            null
-        }
-
-        val errorMessage = "some error occurred"
-        val errorCallback = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onError(IllegalArgumentException(errorMessage))
-            null
-        }
-
-        val uris =
-            (1..20)
-                .map { i ->
-                    val uri = Uri.parse("www.uri$i.com")
-                    if (i == 15) {
-                        doAnswer(errorCallback)
-                            .`when`(mMeasurementManager)
-                            .registerSource(
-                                eq(uri),
-                                any<InputEvent>(),
-                                any<Executor>(),
-                                any<AdServicesOutcomeReceiver<Any, Exception>>()
-                            )
-                    } else {
-                        doAnswer(successCallback)
-                            .`when`(mMeasurementManager)
-                            .registerSource(
-                                eq(uri),
-                                any<InputEvent>(),
-                                any<Executor>(),
-                                any<AdServicesOutcomeReceiver<Any, Exception>>()
-                            )
-                    }
-                    uri
-                }
-                .toList()
-
-        val request = SourceRegistrationRequest(uris, mockInputEvent)
-
-        // Actually invoke the compat code.
-        runBlocking {
-            try {
-                withContext(Dispatchers.Main) { managerCompat!!.registerSourceAsync(request).get() }
-                fail("Expected failure.")
-            } catch (e: ExecutionException) {
-                assertTrue(e.cause!! is IllegalArgumentException)
-                assertThat(e.cause!!.message).isEqualTo(errorMessage)
-            }
-        }
-
-        // Verify that the compat code was invoked correctly.
-        // registerSource gets called 1-20 times. We cannot predict the exact number because
-        // uri15 would crash asynchronously. Other uris may succeed and those threads on default
-        // dispatcher won't crash.
-        verify(mMeasurementManager, atLeastOnce())
-            .registerSource(
-                any<Uri>(),
-                eq(mockInputEvent),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-        verify(mMeasurementManager, atMost(20))
-            .registerSource(
-                any<Uri>(),
-                eq(mockInputEvent),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-    }
-
     @SdkSuppress(minSdkVersion = 30)
     companion object {
 
diff --git a/privacysandbox/ads/ads-adservices/build.gradle b/privacysandbox/ads/ads-adservices/build.gradle
index e35df7a..5610d1a 100644
--- a/privacysandbox/ads/ads-adservices/build.gradle
+++ b/privacysandbox/ads/ads-adservices/build.gradle
@@ -51,10 +51,6 @@
 }
 
 android {
-    buildTypes.all {
-        consumerProguardFiles "proguard-rules.pro"
-    }
-
     compileSdk = 34
     compileSdkExtension = 12
     namespace "androidx.privacysandbox.ads.adservices"
diff --git a/privacysandbox/ads/ads-adservices/proguard-rules.pro b/privacysandbox/ads/ads-adservices/proguard-rules.pro
deleted file mode 100644
index e092df1..0000000
--- a/privacysandbox/ads/ads-adservices/proguard-rules.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-# A rule that will keep the internal ContinuationOutcomeReceiver class used to
-# work with AdServicesOutcomeReceiver on Android R
--keep class androidx.privacysandbox.ads.adservices.internal.ContinuationOutcomeReceiver {
-  <methods>;
-}
diff --git a/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerTest.kt b/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerTest.kt
index b1b53a6..b937f1d 100644
--- a/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerTest.kt
+++ b/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.privacysandbox.ads.adservices.adid
 
-import android.adservices.common.AdServicesOutcomeReceiver
 import android.content.Context
 import android.os.OutcomeReceiver
 import android.os.ext.SdkExtensions
@@ -53,13 +52,12 @@
     private var mSession: StaticMockitoSession? = null
     private val mValidAdServicesSdkExtVersion = AdServicesInfo.adServicesVersion() >= 4
     private val mValidAdExtServicesSdkExtVersionS = AdServicesInfo.extServicesVersionS() >= 9
-    private val mValidAdExtServicesSdkExtVersionR = AdServicesInfo.extServicesVersionR() >= 11
 
     @Before
     fun setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext<Context>())
 
-        if (mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR) {
+        if (mValidAdExtServicesSdkExtVersionS) {
             // setup a mockitoSession to return the mocked manager
             // when the static method .get() is called
             mSession =
@@ -79,16 +77,12 @@
     fun testAdIdOlderVersions() {
         Assume.assumeTrue("maxSdkVersion = API 33 ext 3", !mValidAdServicesSdkExtVersion)
         Assume.assumeTrue("maxSdkVersion = API 31/32 ext 8", !mValidAdExtServicesSdkExtVersionS)
-        Assume.assumeTrue("maxSdkVersion = API 30 ext 10", !mValidAdExtServicesSdkExtVersionR)
         assertThat(AdIdManager.obtain(mContext)).isNull()
     }
 
     @Test
     fun testAdIdManagerNoClassDefFoundError() {
-        Assume.assumeTrue(
-            "minSdkVersion = API 31/32 ext 9 or API 30 ext 11",
-            mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR
-        )
+        Assume.assumeTrue("minSdkVersion = API 31/32 ext 9", mValidAdExtServicesSdkExtVersionS)
 
         `when`(android.adservices.adid.AdIdManager.get(any())).thenThrow(NoClassDefFoundError())
         assertThat(AdIdManager.obtain(mContext)).isNull()
@@ -96,19 +90,13 @@
 
     @Test
     fun testAdIdAsync() {
-        val validExtServicesVersion =
-            mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR
         Assume.assumeTrue(
-            "minSdkVersion = API 33 ext 4 or API 31/32 ext 9 or API 30 ext 11",
-            mValidAdServicesSdkExtVersion || validExtServicesVersion
+            "minSdkVersion = API 33 ext 4 or API 31/32 ext 9",
+            mValidAdServicesSdkExtVersion || mValidAdExtServicesSdkExtVersionS
         )
 
-        val adIdManager = mockAdIdManager(mContext, validExtServicesVersion)
-
-        when (mValidAdExtServicesSdkExtVersionR) {
-            true -> setupResponseR(adIdManager)
-            false -> setupResponseSPlus(adIdManager)
-        }
+        val adIdManager = mockAdIdManager(mContext, mValidAdExtServicesSdkExtVersionS)
+        setupResponseSPlus(adIdManager)
 
         val managerCompat = AdIdManager.obtain(mContext)
 
@@ -116,10 +104,7 @@
         val result = runBlocking { managerCompat!!.getAdId() }
 
         // Verify that the compat code was invoked correctly.
-        when (mValidAdExtServicesSdkExtVersionR) {
-            true -> verifyOnR(adIdManager)
-            false -> verifyOnSPlus(adIdManager)
-        }
+        verifyOnSPlus(adIdManager)
 
         // Verify that the result of the compat call is correct.
         verifyResponse(result)
@@ -162,35 +147,6 @@
                 )
         }
 
-        private fun setupResponseR(adIdManager: android.adservices.adid.AdIdManager) {
-            // Set up the response that AdIdManager will return when the compat code calls it.
-            val adId = android.adservices.adid.AdId("1234", false)
-            val answer = { args: InvocationOnMock ->
-                val receiver =
-                    args.getArgument<
-                        AdServicesOutcomeReceiver<android.adservices.adid.AdId, Exception>
-                    >(
-                        1
-                    )
-                receiver.onResult(adId)
-                null
-            }
-            doAnswer(answer)
-                .`when`(adIdManager)
-                .getAdId(
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<android.adservices.adid.AdId, Exception>>()
-                )
-        }
-
-        private fun verifyOnR(adIdManager: android.adservices.adid.AdIdManager) {
-            verify(adIdManager)
-                .getAdId(
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<android.adservices.adid.AdId, Exception>>()
-                )
-        }
-
         private fun verifyOnSPlus(adIdManager: android.adservices.adid.AdIdManager) {
             verify(adIdManager)
                 .getAdId(
diff --git a/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerTest.kt b/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerTest.kt
index 77ef543..dd323de 100644
--- a/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerTest.kt
+++ b/privacysandbox/ads/ads-adservices/src/androidTest/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.privacysandbox.ads.adservices.measurement
 
-import android.adservices.common.AdServicesOutcomeReceiver
 import android.adservices.measurement.MeasurementManager
 import android.content.Context
 import android.net.Uri
@@ -63,15 +62,12 @@
     private var mSession: StaticMockitoSession? = null
     private val mValidAdServicesSdkExtVersion = AdServicesInfo.adServicesVersion() >= 5
     private val mValidAdExtServicesSdkExtVersionS = AdServicesInfo.extServicesVersionS() >= 9
-    private val mValidAdExtServicesSdkExtVersionR = AdServicesInfo.extServicesVersionR() >= 11
-    private val mValidExtServicesVersion =
-        mValidAdExtServicesSdkExtVersionS || mValidAdExtServicesSdkExtVersionR
 
     @Before
     fun setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext<Context>())
 
-        if (mValidExtServicesVersion) {
+        if (mValidAdExtServicesSdkExtVersionS) {
             // setup a mockitoSession to return the mocked manager
             // when the static method .get() is called
             mSession =
@@ -92,16 +88,12 @@
     fun testMeasurementOlderVersions() {
         Assume.assumeTrue("maxSdkVersion = API 33 ext 4", !mValidAdServicesSdkExtVersion)
         Assume.assumeTrue("maxSdkVersion = API 31/32 ext 8", !mValidAdExtServicesSdkExtVersionS)
-        Assume.assumeTrue("maxSdkVersion = API 30 ext 10", !mValidAdExtServicesSdkExtVersionR)
         assertThat(obtain(mContext)).isNull()
     }
 
     @Test
     fun testMeasurementManagerNoClassDefFoundError() {
-        Assume.assumeTrue(
-            "minSdkVersion = API 31/32 ext 9 or API 30 ext 11",
-            mValidExtServicesVersion
-        )
+        Assume.assumeTrue("minSdkVersion = API 31/32 ext 9", mValidAdExtServicesSdkExtVersionS)
 
         `when`(MeasurementManager.get(any())).thenThrow(NoClassDefFoundError())
         assertThat(obtain(mContext)).isNull()
@@ -503,379 +495,6 @@
         )
     }
 
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testDeleteRegistrationsOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = obtain(mContext)
-
-        // Set up the request.
-        val answer = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(measurementManager)
-            .deleteRegistrations(
-                any<android.adservices.measurement.DeletionRequest>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, java.lang.Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        runBlocking {
-            val request =
-                DeletionRequest(
-                    DeletionRequest.DELETION_MODE_ALL,
-                    DeletionRequest.MATCH_BEHAVIOR_DELETE,
-                    Instant.now(),
-                    Instant.now(),
-                    listOf(uri1),
-                    listOf(uri1)
-                )
-
-            managerCompat!!.deleteRegistrations(request)
-        }
-
-        // Verify that the compat code was invoked correctly.
-        val captor =
-            ArgumentCaptor.forClass(android.adservices.measurement.DeletionRequest::class.java)
-        verify(measurementManager)
-            .deleteRegistrations(
-                captor.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, java.lang.Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        verifyDeletionRequest(captor.value)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterSourceOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val inputEvent = mock(InputEvent::class.java)
-        val managerCompat = obtain(mContext)
-
-        val answer = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(measurementManager)
-            .registerSource(
-                any<Uri>(),
-                any<InputEvent>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        runBlocking { managerCompat!!.registerSource(uri1, inputEvent) }
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 = ArgumentCaptor.forClass(Uri::class.java)
-        val captor2 = ArgumentCaptor.forClass(InputEvent::class.java)
-        verify(measurementManager)
-            .registerSource(
-                captor1.capture(),
-                captor2.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        assertThat(captor1.value == uri1)
-        assertThat(captor2.value == inputEvent)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterTriggerOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = obtain(mContext)
-        val answer = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(measurementManager)
-            .registerTrigger(
-                any<Uri>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Actually invoke the compat code.
-        runBlocking { managerCompat!!.registerTrigger(uri1) }
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 = ArgumentCaptor.forClass(Uri::class.java)
-        verify(measurementManager)
-            .registerTrigger(
-                captor1.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        assertThat(captor1.value).isEqualTo(uri1)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterWebSourceOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = obtain(mContext)
-        val answer = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(measurementManager)
-            .registerWebSource(
-                any<android.adservices.measurement.WebSourceRegistrationRequest>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        val request =
-            WebSourceRegistrationRequest.Builder(listOf(WebSourceParams(uri1, false)), uri1)
-                .setAppDestination(appDestination)
-                .build()
-
-        // Actually invoke the compat code.
-        runBlocking { managerCompat!!.registerWebSource(request) }
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 =
-            ArgumentCaptor.forClass(
-                android.adservices.measurement.WebSourceRegistrationRequest::class.java
-            )
-        verify(measurementManager)
-            .registerWebSource(
-                captor1.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        val actualRequest = captor1.value
-        assertThat(actualRequest.topOriginUri == uri1)
-        assertThat(actualRequest.sourceParams.size == 1)
-        assertThat(actualRequest.appDestination == appDestination)
-        assertThat(actualRequest.sourceParams[0].registrationUri == uri1)
-        assertThat(!actualRequest.sourceParams[0].isDebugKeyAllowed)
-    }
-
-    @ExperimentalFeatures.RegisterSourceOptIn
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterSource_allSuccessOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val mockInputEvent = mock(InputEvent::class.java)
-        val managerCompat = obtain(mContext)
-
-        val successCallback = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(successCallback)
-            .`when`(measurementManager)
-            .registerSource(
-                any<Uri>(),
-                any<InputEvent>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        val request = SourceRegistrationRequest(listOf(uri1, uri2), mockInputEvent)
-
-        // Actually invoke the compat code.
-        runBlocking { managerCompat!!.registerSource(request) }
-
-        // Verify that the compat code was invoked correctly.
-        verify(measurementManager, times(2))
-            .registerSource(
-                any(),
-                eq(mockInputEvent),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-    }
-
-    @ExperimentalFeatures.RegisterSourceOptIn
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterSource_15thOf20Fails_remaining5DoNotExecuteOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val mockInputEvent = mock(InputEvent::class.java)
-        val managerCompat = obtain(mContext)
-
-        val successCallback = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onResult(Object())
-            null
-        }
-
-        val errorMessage = "some error occurred"
-        val errorCallback = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(3)
-            receiver.onError(IllegalArgumentException(errorMessage))
-            null
-        }
-        val uris =
-            (0..20)
-                .map { i ->
-                    val uri = Uri.parse("www.uri$i.com")
-                    if (i == 15) {
-                        doAnswer(errorCallback)
-                            .`when`(measurementManager)
-                            .registerSource(
-                                eq(uri),
-                                any<InputEvent>(),
-                                any<Executor>(),
-                                any<AdServicesOutcomeReceiver<Any, Exception>>()
-                            )
-                    } else {
-                        doAnswer(successCallback)
-                            .`when`(measurementManager)
-                            .registerSource(
-                                eq(uri),
-                                any<InputEvent>(),
-                                any<Executor>(),
-                                any<AdServicesOutcomeReceiver<Any, Exception>>()
-                            )
-                    }
-                    uri
-                }
-                .toList()
-
-        val request = SourceRegistrationRequest(uris, mockInputEvent)
-
-        // Actually invoke the compat code.
-        runBlocking {
-            try {
-                managerCompat!!.registerSource(request)
-                fail("Expected failure.")
-            } catch (e: IllegalArgumentException) {
-                assertThat(e.message).isEqualTo(errorMessage)
-            }
-        }
-
-        // Verify that the compat code was invoked correctly.
-        (0..15).forEach { i ->
-            verify(measurementManager)
-                .registerSource(
-                    eq(Uri.parse("www.uri$i.com")),
-                    eq(mockInputEvent),
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<Any, Exception>>()
-                )
-        }
-        (16..20).forEach { i ->
-            verify(measurementManager, never())
-                .registerSource(
-                    eq(Uri.parse("www.uri$i.com")),
-                    eq(mockInputEvent),
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<Any, Exception>>()
-                )
-        }
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testRegisterWebTriggerOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        val managerCompat = obtain(mContext)
-        val answer = { args: InvocationOnMock ->
-            val receiver = args.getArgument<AdServicesOutcomeReceiver<Any, Exception>>(2)
-            receiver.onResult(Object())
-            null
-        }
-        doAnswer(answer)
-            .`when`(measurementManager)
-            .registerWebTrigger(
-                any<android.adservices.measurement.WebTriggerRegistrationRequest>(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        val request = WebTriggerRegistrationRequest(listOf(WebTriggerParams(uri1, false)), uri2)
-
-        // Actually invoke the compat code.
-        runBlocking { managerCompat!!.registerWebTrigger(request) }
-
-        // Verify that the compat code was invoked correctly.
-        val captor1 =
-            ArgumentCaptor.forClass(
-                android.adservices.measurement.WebTriggerRegistrationRequest::class.java
-            )
-        verify(measurementManager)
-            .registerWebTrigger(
-                captor1.capture(),
-                any<Executor>(),
-                any<AdServicesOutcomeReceiver<Any, Exception>>()
-            )
-
-        // Verify that the request that the compat code makes to the platform is correct.
-        val actualRequest = captor1.value
-        assertThat(actualRequest.destination).isEqualTo(uri2)
-        assertThat(actualRequest.triggerParams.size == 1)
-        assertThat(actualRequest.triggerParams[0].registrationUri == uri1)
-        assertThat(!actualRequest.triggerParams[0].isDebugKeyAllowed)
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testMeasurementApiStatusOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-        callAndVerifyGetMeasurementApiStatusOnR(
-            measurementManager,
-            /* state= */ MeasurementManager.MEASUREMENT_API_STATE_ENABLED,
-            /* expectedResult= */ MeasurementManager.MEASUREMENT_API_STATE_ENABLED
-        )
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 30, minSdkVersion = 30)
-    fun testMeasurementApiStatusUnknownOnR() {
-        Assume.assumeTrue("minSdkVersion = API 30 ext 11", mValidAdExtServicesSdkExtVersionR)
-
-        val measurementManager = mockMeasurementManager(mContext, mValidAdExtServicesSdkExtVersionR)
-
-        // Call with a value greater than values returned in SdkExtensions.AD_SERVICES = 5
-        // Since the compat code does not know the returned state, it sets it to UNKNOWN.
-        callAndVerifyGetMeasurementApiStatusOnR(
-            measurementManager,
-            /* state= */ 6,
-            /* expectedResult= */ 5
-        )
-    }
-
     @SdkSuppress(minSdkVersion = 30)
     companion object {
 
@@ -925,38 +544,6 @@
             assertThat(actualResult == expectedResult)
         }
 
-        private fun callAndVerifyGetMeasurementApiStatusOnR(
-            measurementManager: android.adservices.measurement.MeasurementManager,
-            state: Int,
-            expectedResult: Int
-        ) {
-            val managerCompat = obtain(mContext)
-            val answer = { args: InvocationOnMock ->
-                val receiver = args.getArgument<AdServicesOutcomeReceiver<Int, Exception>>(1)
-                receiver.onResult(state)
-                null
-            }
-            doAnswer(answer)
-                .`when`(measurementManager)
-                .getMeasurementApiStatus(
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<Int, Exception>>()
-                )
-
-            // Actually invoke the compat code.
-            val actualResult = runBlocking { managerCompat!!.getMeasurementApiStatus() }
-
-            // Verify that the compat code was invoked correctly.
-            verify(measurementManager)
-                .getMeasurementApiStatus(
-                    any<Executor>(),
-                    any<AdServicesOutcomeReceiver<Int, Exception>>()
-                )
-
-            // Verify that the request that the compat code makes to the platform is correct.
-            assertThat(actualResult == expectedResult)
-        }
-
         private fun verifyDeletionRequest(request: android.adservices.measurement.DeletionRequest) {
             // Set up the request that we expect the compat code to invoke.
             val expectedRequest =
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManager.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManager.kt
index a0eb9df..df5782a 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManager.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManager.kt
@@ -57,10 +57,6 @@
                 BackCompatManager.getManager(context, "AdIdManager") {
                     AdIdManagerApi31Ext9Impl(context)
                 }
-            } else if (AdServicesInfo.extServicesVersionR() >= 11) {
-                BackCompatManager.getManager(context, "AdIdManager") {
-                    AdIdManagerApi30Ext11Impl(context)
-                }
             } else {
                 null
             }
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerApi30Ext11Impl.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerApi30Ext11Impl.kt
deleted file mode 100644
index 5cd2bf6..0000000
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adid/AdIdManagerApi30Ext11Impl.kt
+++ /dev/null
@@ -1,52 +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.privacysandbox.ads.adservices.adid
-
-import android.adservices.common.AdServicesPermissions
-import android.annotation.SuppressLint
-import android.content.Context
-import android.os.Build
-import androidx.annotation.DoNotInline
-import androidx.annotation.RequiresExtension
-import androidx.annotation.RequiresPermission
-import androidx.annotation.RestrictTo
-import androidx.privacysandbox.ads.adservices.internal.asAdServicesOutcomeReceiver
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-@SuppressLint("ClassVerificationFailure", "NewApi")
-@RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
-open class AdIdManagerApi30Ext11Impl(context: Context) : AdIdManager() {
-    private val mAdIdManager: android.adservices.adid.AdIdManager =
-        android.adservices.adid.AdIdManager.get(context)
-
-    @DoNotInline
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_AD_ID)
-    override suspend fun getAdId(): AdId {
-        return convertResponse(getAdIdAsyncInternal())
-    }
-
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_AD_ID)
-    private suspend fun getAdIdAsyncInternal(): android.adservices.adid.AdId =
-        suspendCancellableCoroutine { continuation ->
-            mAdIdManager.getAdId(Runnable::run, continuation.asAdServicesOutcomeReceiver())
-        }
-
-    private fun convertResponse(response: android.adservices.adid.AdId): AdId {
-        return AdId(response.adId, response.isLimitAdTrackingEnabled)
-    }
-}
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesInfo.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesInfo.kt
index a981294..b28fef0 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesInfo.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesInfo.kt
@@ -38,14 +38,6 @@
         }
     }
 
-    fun extServicesVersionR(): Int {
-        return if (Build.VERSION.SDK_INT == 30) {
-            Extensions30ExtImpl.getAdExtServicesVersionR()
-        } else {
-            0
-        }
-    }
-
     @RequiresApi(30)
     private object Extensions30Impl {
         @DoNotInline
@@ -55,12 +47,8 @@
     @RequiresApi(30)
     private object Extensions30ExtImpl {
         // For ExtServices, there is no AD_SERVICES extension version, so we need to check
-        // for the build version. Use S for now, but this can be changed to R when we add
-        // support for R later.
+        // for the build version for S.
         @DoNotInline
         fun getAdExtServicesVersionS() = SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S)
-
-        @DoNotInline
-        fun getAdExtServicesVersionR() = SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R)
     }
 }
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesOutcomeReceiver.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesOutcomeReceiver.kt
deleted file mode 100644
index 6f87e40..0000000
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/AdServicesOutcomeReceiver.kt
+++ /dev/null
@@ -1,61 +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.privacysandbox.ads.adservices.internal
-
-import android.adservices.common.AdServicesOutcomeReceiver
-import android.annotation.SuppressLint
-import android.os.Build
-import androidx.annotation.RequiresExtension
-import java.util.concurrent.atomic.AtomicBoolean
-import kotlin.coroutines.Continuation
-import kotlin.coroutines.resume
-import kotlin.coroutines.resumeWithException
-
-/*
- This file is a modified version OutcomeReceiver.kt in androidx.core.os, designed to provide the same
- functionality with the AdServicesOutcomeReceiver, to keep the implementation of the backward compatible
- classes as close to identical as possible.
-*/
-
-@RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
-fun <R, E : Throwable> Continuation<R>.asAdServicesOutcomeReceiver():
-    AdServicesOutcomeReceiver<R, E> = ContinuationOutcomeReceiver(this)
-
-@SuppressLint("NewApi")
-@RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
-private class ContinuationOutcomeReceiver<R, E : Throwable>(
-    private val continuation: Continuation<R>
-) : AdServicesOutcomeReceiver<R, E>, AtomicBoolean(false) {
-    @Suppress("WRONG_NULLABILITY_FOR_JAVA_OVERRIDE")
-    override fun onResult(result: R) {
-        // Do not attempt to resume more than once, even if the caller of the returned
-        // OutcomeReceiver is buggy and tries anyway.
-        if (compareAndSet(false, true)) {
-            continuation.resume(result)
-        }
-    }
-
-    override fun onError(error: E) {
-        // Do not attempt to resume more than once, even if the caller of the returned
-        // OutcomeReceiver is buggy and tries anyway.
-        if (compareAndSet(false, true)) {
-            continuation.resumeWithException(error)
-        }
-    }
-
-    override fun toString() = "ContinuationOutcomeReceiver(outcomeReceived = ${get()})"
-}
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/BackCompatManager.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/BackCompatManager.kt
index f0f6005..f796274 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/BackCompatManager.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/internal/BackCompatManager.kt
@@ -29,7 +29,6 @@
             Log.d(
                 tag,
                 "Unable to find adservices code, check manifest for uses-library tag, " +
-                    "versionR=${AdServicesInfo.extServicesVersionR()}, " +
                     "versionS=${AdServicesInfo.extServicesVersionS()}"
             )
             return null
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/DeletionRequest.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/DeletionRequest.kt
index a482855..14782a9 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/DeletionRequest.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/DeletionRequest.kt
@@ -100,7 +100,6 @@
     @SuppressLint("ClassVerificationFailure", "NewApi")
     @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 4)
     @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9)
-    @RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
     internal fun convertToAdServices(): android.adservices.measurement.DeletionRequest {
         return android.adservices.measurement.DeletionRequest.Builder()
             .setDeletionMode(deletionMode)
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt
index ebfdc16..ea8584b 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt
@@ -149,10 +149,6 @@
                 BackCompatManager.getManager(context, "MeasurementManager") {
                     MeasurementManagerApi31Ext9Impl(context)
                 }
-            } else if (AdServicesInfo.extServicesVersionR() >= 11) {
-                BackCompatManager.getManager(context, "MeasurementManager") {
-                    MeasurementManagerApi30Ext11Impl(context)
-                }
             } else {
                 null
             }
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerApi30Ext11Impl.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerApi30Ext11Impl.kt
deleted file mode 100644
index 86ed67c..0000000
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManagerApi30Ext11Impl.kt
+++ /dev/null
@@ -1,129 +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.privacysandbox.ads.adservices.measurement
-
-import android.adservices.common.AdServicesPermissions
-import android.annotation.SuppressLint
-import android.content.Context
-import android.net.Uri
-import android.os.Build
-import android.view.InputEvent
-import androidx.annotation.DoNotInline
-import androidx.annotation.RequiresExtension
-import androidx.annotation.RequiresPermission
-import androidx.annotation.RestrictTo
-import androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures
-import androidx.privacysandbox.ads.adservices.internal.asAdServicesOutcomeReceiver
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-@SuppressLint("ClassVerificationFailure", "NewApi")
-@RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
-class MeasurementManagerApi30Ext11Impl(context: Context) : MeasurementManager() {
-    private val mMeasurementManager: android.adservices.measurement.MeasurementManager =
-        android.adservices.measurement.MeasurementManager.get(context)
-
-    @DoNotInline
-    override suspend fun deleteRegistrations(deletionRequest: DeletionRequest) {
-        suspendCancellableCoroutine<Any> { continuation ->
-            mMeasurementManager.deleteRegistrations(
-                deletionRequest.convertToAdServices(),
-                Runnable::run,
-                continuation.asAdServicesOutcomeReceiver()
-            )
-        }
-    }
-
-    @DoNotInline
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION)
-    override suspend fun registerSource(attributionSource: Uri, inputEvent: InputEvent?) {
-        suspendCancellableCoroutine<Any> { continuation ->
-            mMeasurementManager.registerSource(
-                attributionSource,
-                inputEvent,
-                Runnable::run,
-                continuation.asAdServicesOutcomeReceiver()
-            )
-        }
-    }
-
-    @DoNotInline
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION)
-    override suspend fun registerTrigger(trigger: Uri) {
-        suspendCancellableCoroutine<Any> { continuation ->
-            mMeasurementManager.registerTrigger(
-                trigger,
-                Runnable::run,
-                continuation.asAdServicesOutcomeReceiver()
-            )
-        }
-    }
-
-    @DoNotInline
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION)
-    override suspend fun registerWebSource(request: WebSourceRegistrationRequest) {
-        suspendCancellableCoroutine<Any> { continuation ->
-            mMeasurementManager.registerWebSource(
-                request.convertToAdServices(),
-                Runnable::run,
-                continuation.asAdServicesOutcomeReceiver()
-            )
-        }
-    }
-
-    @DoNotInline
-    @ExperimentalFeatures.RegisterSourceOptIn
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION)
-    override suspend fun registerSource(request: SourceRegistrationRequest): Unit = coroutineScope {
-        request.registrationUris.forEach { uri ->
-            launch {
-                suspendCancellableCoroutine<Any> { continuation ->
-                    mMeasurementManager.registerSource(
-                        uri,
-                        request.inputEvent,
-                        Runnable::run,
-                        continuation.asAdServicesOutcomeReceiver()
-                    )
-                }
-            }
-        }
-    }
-
-    @DoNotInline
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION)
-    override suspend fun registerWebTrigger(request: WebTriggerRegistrationRequest) {
-        suspendCancellableCoroutine<Any> { continuation ->
-            mMeasurementManager.registerWebTrigger(
-                request.convertToAdServices(),
-                Runnable::run,
-                continuation.asAdServicesOutcomeReceiver()
-            )
-        }
-    }
-
-    @DoNotInline
-    @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION)
-    override suspend fun getMeasurementApiStatus(): Int =
-        suspendCancellableCoroutine { continuation ->
-            mMeasurementManager.getMeasurementApiStatus(
-                Runnable::run,
-                continuation.asAdServicesOutcomeReceiver()
-            )
-        }
-}
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceParams.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceParams.kt
index c7bc6fe..1d3218f 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceParams.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceParams.kt
@@ -54,7 +54,6 @@
         @SuppressLint("ClassVerificationFailure", "NewApi")
         @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 4)
         @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9)
-        @RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
         internal fun convertWebSourceParams(
             request: List<WebSourceParams>
         ): List<android.adservices.measurement.WebSourceParams> {
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceRegistrationRequest.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceRegistrationRequest.kt
index 5d48214..6499e73 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceRegistrationRequest.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebSourceRegistrationRequest.kt
@@ -95,7 +95,6 @@
     @SuppressLint("ClassVerificationFailure", "NewApi")
     @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 4)
     @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9)
-    @RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
     internal fun convertToAdServices():
         android.adservices.measurement.WebSourceRegistrationRequest {
         return android.adservices.measurement.WebSourceRegistrationRequest.Builder(
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerParams.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerParams.kt
index 2163701..bc3eefc 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerParams.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerParams.kt
@@ -54,7 +54,6 @@
         @SuppressLint("ClassVerificationFailure", "NewApi")
         @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 4)
         @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9)
-        @RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
         internal fun convertWebTriggerParams(
             request: List<WebTriggerParams>
         ): List<android.adservices.measurement.WebTriggerParams> {
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerRegistrationRequest.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerRegistrationRequest.kt
index f521339..7384929 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerRegistrationRequest.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/WebTriggerRegistrationRequest.kt
@@ -52,7 +52,6 @@
     @SuppressLint("ClassVerificationFailure", "NewApi")
     @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 4)
     @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9)
-    @RequiresExtension(extension = Build.VERSION_CODES.R, version = 11)
     internal fun convertToAdServices():
         android.adservices.measurement.WebTriggerRegistrationRequest {
         return android.adservices.measurement.WebTriggerRegistrationRequest.Builder(
diff --git a/privacysandbox/tools/tools-apicompiler/build.gradle b/privacysandbox/tools/tools-apicompiler/build.gradle
index ec701e3..27258e4 100644
--- a/privacysandbox/tools/tools-apicompiler/build.gradle
+++ b/privacysandbox/tools/tools-apicompiler/build.gradle
@@ -21,6 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
+
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.SdkHelperKt
 import androidx.build.AndroidXConfig
@@ -80,4 +82,5 @@
     type = LibraryType.ANNOTATION_PROCESSOR
     inceptionYear = "2022"
     description = "Compiler for Privacy Sandbox API annotations."
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/room/room-compiler/build.gradle b/room/room-compiler/build.gradle
index ff0e1d5..060f27d 100644
--- a/room/room-compiler/build.gradle
+++ b/room/room-compiler/build.gradle
@@ -23,6 +23,7 @@
  */
 
 import androidx.build.BuildOnServerKt
+import androidx.build.KotlinTarget
 import androidx.build.LibraryType
 import androidx.build.SdkHelperKt
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -240,4 +241,5 @@
     type = LibraryType.ANNOTATION_PROCESSOR
     inceptionYear = "2017"
     description = "Android Room annotation processor"
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/room/room-migration/build.gradle b/room/room-migration/build.gradle
index b10beda..8051a15 100644
--- a/room/room-migration/build.gradle
+++ b/room/room-migration/build.gradle
@@ -22,6 +22,8 @@
  * modifying its settings.
  */
 
+
+import androidx.build.KotlinTarget
 import androidx.build.PlatformIdentifier
 import androidx.build.LibraryType
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
@@ -88,4 +90,5 @@
     description = "Android Room Migration"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = false
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/room/room-testing/build.gradle b/room/room-testing/build.gradle
index 13685a4..14a4823 100644
--- a/room/room-testing/build.gradle
+++ b/room/room-testing/build.gradle
@@ -22,6 +22,8 @@
  * modifying its settings.
  */
 
+
+import androidx.build.KotlinTarget
 import androidx.build.PlatformIdentifier
 import androidx.build.LibraryType
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
@@ -97,4 +99,5 @@
     description = "Android Room Testing"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = false
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/settings.gradle b/settings.gradle
index 257a374..ded0605 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -658,6 +658,7 @@
 includeProject(":datastore:datastore-rxjava2", [BuildType.MAIN, BuildType.INFRAROGUE, BuildType.KMP])
 includeProject(":datastore:datastore-rxjava3", [BuildType.MAIN, BuildType.INFRAROGUE, BuildType.KMP])
 includeProject(":datastore:datastore-sampleapp", [BuildType.MAIN, BuildType.INFRAROGUE, BuildType.KMP])
+includeProject(":datastore:integration-tests:testapp", [BuildType.MAIN])
 includeProject(":documentfile:documentfile", [BuildType.MAIN])
 includeProject(":draganddrop:draganddrop", [BuildType.MAIN])
 includeProject(":draganddrop:integration-tests:sampleapp", [BuildType.MAIN])
diff --git a/stableaidl/stableaidl-gradle-plugin/build.gradle b/stableaidl/stableaidl-gradle-plugin/build.gradle
index 4518da8..a0c775c 100644
--- a/stableaidl/stableaidl-gradle-plugin/build.gradle
+++ b/stableaidl/stableaidl-gradle-plugin/build.gradle
@@ -21,7 +21,8 @@
  * Please use that script when creating a new project, rather than copying an existing project and
  * modifying its settings.
  */
-import androidx.build.*
+import androidx.build.KotlinTarget
+import androidx.build.LibraryType
 
 plugins {
     id("AndroidXPlugin")
@@ -85,4 +86,5 @@
     type = LibraryType.GRADLE_PLUGIN
     inceptionYear = "2022"
     description = "Stable AIDL Gradle Plugin"
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
diff --git a/wear/compose/compose-foundation/build.gradle b/wear/compose/compose-foundation/build.gradle
index aa8f032..4844a72 100644
--- a/wear/compose/compose-foundation/build.gradle
+++ b/wear/compose/compose-foundation/build.gradle
@@ -32,14 +32,14 @@
 }
 
 dependencies {
-    api("androidx.compose.foundation:foundation:1.7.0-rc01")
-    api("androidx.compose.ui:ui:1.7.0-rc01")
-    api("androidx.compose.ui:ui-text:1.7.0-rc01")
-    api("androidx.compose.runtime:runtime:1.7.0-rc01")
+    api("androidx.compose.foundation:foundation:1.7.0")
+    api("androidx.compose.ui:ui:1.7.0")
+    api("androidx.compose.ui:ui-text:1.7.0")
+    api("androidx.compose.runtime:runtime:1.7.0")
 
     implementation(libs.kotlinStdlib)
-    implementation("androidx.compose.foundation:foundation-layout:1.7.0-rc01")
-    implementation("androidx.compose.ui:ui-util:1.7.0-rc01")
+    implementation("androidx.compose.foundation:foundation-layout:1.7.0")
+    implementation("androidx.compose.ui:ui-util:1.7.0")
     implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
     implementation("androidx.core:core:1.12.0")
     implementation("androidx.profileinstaller:profileinstaller:1.3.1")
diff --git a/wear/compose/compose-material-core/build.gradle b/wear/compose/compose-material-core/build.gradle
index e380531..df1b6c6 100644
--- a/wear/compose/compose-material-core/build.gradle
+++ b/wear/compose/compose-material-core/build.gradle
@@ -33,16 +33,16 @@
 }
 
 dependencies {
-    api("androidx.compose.foundation:foundation:1.7.0-rc01")
-    api("androidx.compose.ui:ui:1.7.0-rc01")
-    api("androidx.compose.ui:ui-text:1.7.0-rc01")
-    api("androidx.compose.runtime:runtime:1.7.0-rc01")
+    api("androidx.compose.foundation:foundation:1.7.0")
+    api("androidx.compose.ui:ui:1.7.0")
+    api("androidx.compose.ui:ui-text:1.7.0")
+    api("androidx.compose.runtime:runtime:1.7.0")
 
     implementation(libs.kotlinStdlib)
-    implementation("androidx.compose.animation:animation:1.7.0-rc01")
-    implementation("androidx.compose.material:material-icons-core:1.7.0-rc01")
-    implementation("androidx.compose.material:material-ripple:1.7.0-rc01")
-    implementation("androidx.compose.ui:ui-util:1.7.0-rc01")
+    implementation("androidx.compose.animation:animation:1.7.0")
+    implementation("androidx.compose.material:material-icons-core:1.7.0")
+    implementation("androidx.compose.material:material-ripple:1.7.0")
+    implementation("androidx.compose.ui:ui-util:1.7.0")
     implementation(project(":wear:compose:compose-foundation"))
     implementation("androidx.profileinstaller:profileinstaller:1.3.1")
 
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Resources.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Resources.kt
index 1a967f1..7b9faf1 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Resources.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Resources.kt
@@ -62,11 +62,11 @@
 
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 @Composable
-fun screenHeightDp() = LocalContext.current.resources.configuration.screenHeightDp
+fun screenHeightDp() = LocalConfiguration.current.screenHeightDp
 
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 @Composable
-fun screenWidthDp() = LocalContext.current.resources.configuration.screenWidthDp
+fun screenWidthDp() = LocalConfiguration.current.screenWidthDp
 
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 @Composable
diff --git a/wear/compose/compose-material/build.gradle b/wear/compose/compose-material/build.gradle
index 864af0d..1d2fc79 100644
--- a/wear/compose/compose-material/build.gradle
+++ b/wear/compose/compose-material/build.gradle
@@ -31,17 +31,17 @@
 }
 
 dependencies {
-    api("androidx.compose.foundation:foundation:1.7.0-rc01")
-    api("androidx.compose.ui:ui:1.7.0-rc01")
-    api("androidx.compose.ui:ui-text:1.7.0-rc01")
-    api("androidx.compose.runtime:runtime:1.7.0-rc01")
+    api("androidx.compose.foundation:foundation:1.7.0")
+    api("androidx.compose.ui:ui:1.7.0")
+    api("androidx.compose.ui:ui-text:1.7.0")
+    api("androidx.compose.runtime:runtime:1.7.0")
     api(project(":wear:compose:compose-foundation"))
 
     implementation(libs.kotlinStdlib)
-    implementation("androidx.compose.animation:animation:1.7.0-rc01")
-    implementation("androidx.compose.material:material-icons-core:1.7.0-rc01")
-    implementation("androidx.compose.material:material-ripple:1.7.0-rc01")
-    implementation("androidx.compose.ui:ui-util:1.7.0-rc01")
+    implementation("androidx.compose.animation:animation:1.7.0")
+    implementation("androidx.compose.material:material-icons-core:1.7.0")
+    implementation("androidx.compose.material:material-ripple:1.7.0")
+    implementation("androidx.compose.ui:ui-util:1.7.0")
     implementation(project(":wear:compose:compose-material-core"))
     implementation("androidx.profileinstaller:profileinstaller:1.3.1")
     implementation("androidx.lifecycle:lifecycle-common:2.7.0")
diff --git a/wear/compose/compose-material3/api/current.txt b/wear/compose/compose-material3/api/current.txt
index 3b402a4..b0b63b9 100644
--- a/wear/compose/compose-material3/api/current.txt
+++ b/wear/compose/compose-material3/api/current.txt
@@ -1,6 +1,28 @@
 // Signature format: 4.0
 package androidx.wear.compose.material3 {
 
+  public final class AlertDialogDefaults {
+    method @androidx.compose.runtime.Composable public void BottomButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public void ConfirmButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public void DismissButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public void GroupSeparator();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues contentPadding(boolean hasBottomButton);
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getConfirmIcon();
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getDismissIcon();
+    method public float getEdgeButtonExtraTopPadding();
+    method public androidx.compose.foundation.layout.Arrangement.Vertical getVerticalArrangement();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> ConfirmIcon;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> DismissIcon;
+    property public final androidx.compose.foundation.layout.Arrangement.Vertical VerticalArrangement;
+    property public final float edgeButtonExtraTopPadding;
+    field public static final androidx.wear.compose.material3.AlertDialogDefaults INSTANCE;
+  }
+
+  public final class AlertDialogKt {
+    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> bottomButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
+    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> confirmButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
+  }
+
   @RequiresApi(31) public final class AnimatedTextDefaults {
     field public static final int CacheSize = 5; // 0x5
     field public static final androidx.wear.compose.material3.AnimatedTextDefaults INSTANCE;
@@ -298,6 +320,45 @@
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
   }
 
+  public final class ConfirmationColors {
+    ctor public ConfirmationColors(long iconColor, long iconContainerColor, long textColor);
+    method public long getIconColor();
+    method public long getIconContainerColor();
+    method public long getTextColor();
+    property public final long iconColor;
+    property public final long iconContainerColor;
+    property public final long textColor;
+  }
+
+  public final class ConfirmationDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors confirmationColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors confirmationColors(optional long iconColor, optional long iconContainerColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> curvedText(String text, optional androidx.wear.compose.foundation.CurvedTextStyle style);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors failureColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors failureColors(optional long iconColor, optional long iconContainerColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> failureText();
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> getFailureIcon();
+    method public float getIconSize();
+    method public float getSmallIconSize();
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> getSuccessIcon();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors successColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors successColors(optional long iconColor, optional long iconContainerColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> successText();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> FailureIcon;
+    property public final float IconSize;
+    property public final float SmallIconSize;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> SuccessIcon;
+    field public static final long ConfirmationDurationMillis = 4000L; // 0xfa0L
+    field public static final androidx.wear.compose.material3.ConfirmationDefaults INSTANCE;
+  }
+
+  public final class ConfirmationKt {
+    method @androidx.compose.runtime.Composable public static void Confirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? text, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Confirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FailureConfirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void SuccessConfirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class ContentColorKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
@@ -401,8 +462,8 @@
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors();
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
     method public float iconSizeFor(float size);
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors iconToggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors iconToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconToggleButtonColors iconToggleButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconToggleButtonColors iconToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors();
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors(optional long contentColor, optional long disabledContentColor);
     property public final float DefaultButtonSize;
@@ -422,7 +483,7 @@
     method @androidx.compose.runtime.Composable public static void FilledIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.ToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
   }
 
@@ -432,6 +493,26 @@
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
+  @androidx.compose.runtime.Immutable public final class IconToggleButtonColors {
+    ctor public IconToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
+    method public long getCheckedContainerColor();
+    method public long getCheckedContentColor();
+    method public long getDisabledCheckedContainerColor();
+    method public long getDisabledCheckedContentColor();
+    method public long getDisabledUncheckedContainerColor();
+    method public long getDisabledUncheckedContentColor();
+    method public long getUncheckedContainerColor();
+    method public long getUncheckedContentColor();
+    property public final long checkedContainerColor;
+    property public final long checkedContentColor;
+    property public final long disabledCheckedContainerColor;
+    property public final long disabledCheckedContentColor;
+    property public final long disabledUncheckedContainerColor;
+    property public final long disabledUncheckedContentColor;
+    property public final long uncheckedContainerColor;
+    property public final long uncheckedContentColor;
+  }
+
   @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.wear.compose.material3.ExperimentalWearMaterial3Api public final class InlineSliderColors {
     ctor public InlineSliderColors(long containerColor, long buttonIconColor, long selectedBarColor, long unselectedBarColor, long barSeparatorColor, long disabledContainerColor, long disabledButtonIconColor, long disabledSelectedBarColor, long disabledUnselectedBarColor, long disabledBarSeparatorColor);
     method public long getBarSeparatorColor();
@@ -548,6 +629,34 @@
     method public static androidx.wear.compose.material3.MotionScheme standardMotionScheme();
   }
 
+  public final class OpenOnPhoneDialogColors {
+    ctor public OpenOnPhoneDialogColors(long iconColor, long iconContainerColor, long progressIndicatorColor, long progressTrackColor, long textColor);
+    method public long getIconColor();
+    method public long getIconContainerColor();
+    method public long getProgressIndicatorColor();
+    method public long getProgressTrackColor();
+    method public long getTextColor();
+    property public final long iconColor;
+    property public final long iconContainerColor;
+    property public final long progressIndicatorColor;
+    property public final long progressTrackColor;
+    property public final long textColor;
+  }
+
+  public final class OpenOnPhoneDialogDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.OpenOnPhoneDialogColors colors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.OpenOnPhoneDialogColors colors(optional long iconColor, optional long iconContainerColor, optional long progressIndicatorColor, optional long progressTrackColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> curvedText(optional String text, optional androidx.wear.compose.foundation.CurvedTextStyle style);
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> getIcon();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> Icon;
+    field public static final long DurationMillis = 4000L; // 0xfa0L
+    field public static final androidx.wear.compose.material3.OpenOnPhoneDialogDefaults INSTANCE;
+  }
+
+  public final class OpenOnPhoneDialogKt {
+    method @androidx.compose.runtime.Composable public static void OpenOnPhoneDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.wear.compose.material3.OpenOnPhoneDialogColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class PickerDefaults {
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.gestures.FlingBehavior flingBehavior(androidx.wear.compose.material3.PickerState state, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float> decay);
     method public float getGradientRatio();
@@ -1119,8 +1228,8 @@
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextButtonColors outlinedTextButtonColors(optional long contentColor, optional long disabledContentColor);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextButtonColors textButtonColors();
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextButtonColors textButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors textToggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors textToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextToggleButtonColors textToggleButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextToggleButtonColors textToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
     property public final float DefaultButtonSize;
     property public final float LargeButtonSize;
     property public final float SmallButtonSize;
@@ -1134,7 +1243,7 @@
 
   public final class TextButtonKt {
     method @androidx.compose.runtime.Composable public static void TextButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.TextButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void TextToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.ToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void TextToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.TextToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
   }
 
   public final class TextKt {
@@ -1151,6 +1260,26 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
   }
 
+  @androidx.compose.runtime.Immutable public final class TextToggleButtonColors {
+    ctor public TextToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
+    method public long getCheckedContainerColor();
+    method public long getCheckedContentColor();
+    method public long getDisabledCheckedContainerColor();
+    method public long getDisabledCheckedContentColor();
+    method public long getDisabledUncheckedContainerColor();
+    method public long getDisabledUncheckedContentColor();
+    method public long getUncheckedContainerColor();
+    method public long getUncheckedContentColor();
+    property public final long checkedContainerColor;
+    property public final long checkedContentColor;
+    property public final long disabledCheckedContainerColor;
+    property public final long disabledCheckedContentColor;
+    property public final long disabledUncheckedContainerColor;
+    property public final long disabledUncheckedContentColor;
+    property public final long uncheckedContainerColor;
+    property public final long uncheckedContentColor;
+  }
+
   @androidx.compose.runtime.Immutable public final class TimePickerColors {
     ctor public TimePickerColors(long selectedPickerContentColor, long unselectedPickerContentColor, long separatorColor, long pickerLabelColor, long confirmButtonContentColor, long confirmButtonContainerColor);
     method public long getConfirmButtonContainerColor();
@@ -1221,26 +1350,6 @@
     method public abstract void time();
   }
 
-  @androidx.compose.runtime.Immutable public final class ToggleButtonColors {
-    ctor public ToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
-    method public long getCheckedContainerColor();
-    method public long getCheckedContentColor();
-    method public long getDisabledCheckedContainerColor();
-    method public long getDisabledCheckedContentColor();
-    method public long getDisabledUncheckedContainerColor();
-    method public long getDisabledUncheckedContentColor();
-    method public long getUncheckedContainerColor();
-    method public long getUncheckedContentColor();
-    property public final long checkedContainerColor;
-    property public final long checkedContentColor;
-    property public final long disabledCheckedContainerColor;
-    property public final long disabledCheckedContentColor;
-    property public final long disabledUncheckedContainerColor;
-    property public final long disabledUncheckedContentColor;
-    property public final long uncheckedContainerColor;
-    property public final long uncheckedContentColor;
-  }
-
   public fun interface TouchExplorationStateProvider {
     method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<java.lang.Boolean> touchExplorationState();
   }
@@ -1296,32 +1405,6 @@
 
 }
 
-package androidx.wear.compose.material3.dialog {
-
-  public final class AlertDialogDefaults {
-    method @androidx.compose.runtime.Composable public void BottomButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public void ConfirmButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public void DismissButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public void GroupSeparator();
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues contentPadding(boolean hasBottomButton);
-    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getConfirmIcon();
-    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getDismissIcon();
-    method public float getEdgeButtonExtraTopPadding();
-    method public androidx.compose.foundation.layout.Arrangement.Vertical getVerticalArrangement();
-    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> ConfirmIcon;
-    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> DismissIcon;
-    property public final androidx.compose.foundation.layout.Arrangement.Vertical VerticalArrangement;
-    property public final float edgeButtonExtraTopPadding;
-    field public static final androidx.wear.compose.material3.dialog.AlertDialogDefaults INSTANCE;
-  }
-
-  public final class AlertDialogKt {
-    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> bottomButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
-    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> confirmButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
-  }
-
-}
-
 package androidx.wear.compose.material3.lazy {
 
   public final class LazyColumnScrollTransformModifiersKt {
diff --git a/wear/compose/compose-material3/api/restricted_current.txt b/wear/compose/compose-material3/api/restricted_current.txt
index 3b402a4..b0b63b9 100644
--- a/wear/compose/compose-material3/api/restricted_current.txt
+++ b/wear/compose/compose-material3/api/restricted_current.txt
@@ -1,6 +1,28 @@
 // Signature format: 4.0
 package androidx.wear.compose.material3 {
 
+  public final class AlertDialogDefaults {
+    method @androidx.compose.runtime.Composable public void BottomButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public void ConfirmButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public void DismissButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public void GroupSeparator();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues contentPadding(boolean hasBottomButton);
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getConfirmIcon();
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getDismissIcon();
+    method public float getEdgeButtonExtraTopPadding();
+    method public androidx.compose.foundation.layout.Arrangement.Vertical getVerticalArrangement();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> ConfirmIcon;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> DismissIcon;
+    property public final androidx.compose.foundation.layout.Arrangement.Vertical VerticalArrangement;
+    property public final float edgeButtonExtraTopPadding;
+    field public static final androidx.wear.compose.material3.AlertDialogDefaults INSTANCE;
+  }
+
+  public final class AlertDialogKt {
+    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> bottomButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
+    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> confirmButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
+  }
+
   @RequiresApi(31) public final class AnimatedTextDefaults {
     field public static final int CacheSize = 5; // 0x5
     field public static final androidx.wear.compose.material3.AnimatedTextDefaults INSTANCE;
@@ -298,6 +320,45 @@
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
   }
 
+  public final class ConfirmationColors {
+    ctor public ConfirmationColors(long iconColor, long iconContainerColor, long textColor);
+    method public long getIconColor();
+    method public long getIconContainerColor();
+    method public long getTextColor();
+    property public final long iconColor;
+    property public final long iconContainerColor;
+    property public final long textColor;
+  }
+
+  public final class ConfirmationDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors confirmationColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors confirmationColors(optional long iconColor, optional long iconContainerColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> curvedText(String text, optional androidx.wear.compose.foundation.CurvedTextStyle style);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors failureColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors failureColors(optional long iconColor, optional long iconContainerColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> failureText();
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> getFailureIcon();
+    method public float getIconSize();
+    method public float getSmallIconSize();
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> getSuccessIcon();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors successColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ConfirmationColors successColors(optional long iconColor, optional long iconContainerColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> successText();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> FailureIcon;
+    property public final float IconSize;
+    property public final float SmallIconSize;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> SuccessIcon;
+    field public static final long ConfirmationDurationMillis = 4000L; // 0xfa0L
+    field public static final androidx.wear.compose.material3.ConfirmationDefaults INSTANCE;
+  }
+
+  public final class ConfirmationKt {
+    method @androidx.compose.runtime.Composable public static void Confirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? text, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Confirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FailureConfirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void SuccessConfirmation(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.wear.compose.material3.ConfirmationColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class ContentColorKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
@@ -401,8 +462,8 @@
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors();
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
     method public float iconSizeFor(float size);
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors iconToggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors iconToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconToggleButtonColors iconToggleButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconToggleButtonColors iconToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors();
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonColors outlinedIconButtonColors(optional long contentColor, optional long disabledContentColor);
     property public final float DefaultButtonSize;
@@ -422,7 +483,7 @@
     method @androidx.compose.runtime.Composable public static void FilledIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.ToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
   }
 
@@ -432,6 +493,26 @@
     method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
+  @androidx.compose.runtime.Immutable public final class IconToggleButtonColors {
+    ctor public IconToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
+    method public long getCheckedContainerColor();
+    method public long getCheckedContentColor();
+    method public long getDisabledCheckedContainerColor();
+    method public long getDisabledCheckedContentColor();
+    method public long getDisabledUncheckedContainerColor();
+    method public long getDisabledUncheckedContentColor();
+    method public long getUncheckedContainerColor();
+    method public long getUncheckedContentColor();
+    property public final long checkedContainerColor;
+    property public final long checkedContentColor;
+    property public final long disabledCheckedContainerColor;
+    property public final long disabledCheckedContentColor;
+    property public final long disabledUncheckedContainerColor;
+    property public final long disabledUncheckedContentColor;
+    property public final long uncheckedContainerColor;
+    property public final long uncheckedContentColor;
+  }
+
   @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.wear.compose.material3.ExperimentalWearMaterial3Api public final class InlineSliderColors {
     ctor public InlineSliderColors(long containerColor, long buttonIconColor, long selectedBarColor, long unselectedBarColor, long barSeparatorColor, long disabledContainerColor, long disabledButtonIconColor, long disabledSelectedBarColor, long disabledUnselectedBarColor, long disabledBarSeparatorColor);
     method public long getBarSeparatorColor();
@@ -548,6 +629,34 @@
     method public static androidx.wear.compose.material3.MotionScheme standardMotionScheme();
   }
 
+  public final class OpenOnPhoneDialogColors {
+    ctor public OpenOnPhoneDialogColors(long iconColor, long iconContainerColor, long progressIndicatorColor, long progressTrackColor, long textColor);
+    method public long getIconColor();
+    method public long getIconContainerColor();
+    method public long getProgressIndicatorColor();
+    method public long getProgressTrackColor();
+    method public long getTextColor();
+    property public final long iconColor;
+    property public final long iconContainerColor;
+    property public final long progressIndicatorColor;
+    property public final long progressTrackColor;
+    property public final long textColor;
+  }
+
+  public final class OpenOnPhoneDialogDefaults {
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.OpenOnPhoneDialogColors colors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.OpenOnPhoneDialogColors colors(optional long iconColor, optional long iconContainerColor, optional long progressIndicatorColor, optional long progressTrackColor, optional long textColor);
+    method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function1<androidx.wear.compose.foundation.CurvedScope,kotlin.Unit> curvedText(optional String text, optional androidx.wear.compose.foundation.CurvedTextStyle style);
+    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> getIcon();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.BoxScope,kotlin.Unit> Icon;
+    field public static final long DurationMillis = 4000L; // 0xfa0L
+    field public static final androidx.wear.compose.material3.OpenOnPhoneDialogDefaults INSTANCE;
+  }
+
+  public final class OpenOnPhoneDialogKt {
+    method @androidx.compose.runtime.Composable public static void OpenOnPhoneDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.CurvedScope,kotlin.Unit>? curvedText, optional androidx.wear.compose.material3.OpenOnPhoneDialogColors colors, optional androidx.compose.ui.window.DialogProperties properties, optional long durationMillis, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class PickerDefaults {
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.gestures.FlingBehavior flingBehavior(androidx.wear.compose.material3.PickerState state, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float> decay);
     method public float getGradientRatio();
@@ -1119,8 +1228,8 @@
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextButtonColors outlinedTextButtonColors(optional long contentColor, optional long disabledContentColor);
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextButtonColors textButtonColors();
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextButtonColors textButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors textToggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors textToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextToggleButtonColors textToggleButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.TextToggleButtonColors textToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor);
     property public final float DefaultButtonSize;
     property public final float LargeButtonSize;
     property public final float SmallButtonSize;
@@ -1134,7 +1243,7 @@
 
   public final class TextButtonKt {
     method @androidx.compose.runtime.Composable public static void TextButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional String? onLongClickLabel, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.TextButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void TextToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.ToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void TextToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.wear.compose.material3.TextToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
   }
 
   public final class TextKt {
@@ -1151,6 +1260,26 @@
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
   }
 
+  @androidx.compose.runtime.Immutable public final class TextToggleButtonColors {
+    ctor public TextToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
+    method public long getCheckedContainerColor();
+    method public long getCheckedContentColor();
+    method public long getDisabledCheckedContainerColor();
+    method public long getDisabledCheckedContentColor();
+    method public long getDisabledUncheckedContainerColor();
+    method public long getDisabledUncheckedContentColor();
+    method public long getUncheckedContainerColor();
+    method public long getUncheckedContentColor();
+    property public final long checkedContainerColor;
+    property public final long checkedContentColor;
+    property public final long disabledCheckedContainerColor;
+    property public final long disabledCheckedContentColor;
+    property public final long disabledUncheckedContainerColor;
+    property public final long disabledUncheckedContentColor;
+    property public final long uncheckedContainerColor;
+    property public final long uncheckedContentColor;
+  }
+
   @androidx.compose.runtime.Immutable public final class TimePickerColors {
     ctor public TimePickerColors(long selectedPickerContentColor, long unselectedPickerContentColor, long separatorColor, long pickerLabelColor, long confirmButtonContentColor, long confirmButtonContainerColor);
     method public long getConfirmButtonContainerColor();
@@ -1221,26 +1350,6 @@
     method public abstract void time();
   }
 
-  @androidx.compose.runtime.Immutable public final class ToggleButtonColors {
-    ctor public ToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
-    method public long getCheckedContainerColor();
-    method public long getCheckedContentColor();
-    method public long getDisabledCheckedContainerColor();
-    method public long getDisabledCheckedContentColor();
-    method public long getDisabledUncheckedContainerColor();
-    method public long getDisabledUncheckedContentColor();
-    method public long getUncheckedContainerColor();
-    method public long getUncheckedContentColor();
-    property public final long checkedContainerColor;
-    property public final long checkedContentColor;
-    property public final long disabledCheckedContainerColor;
-    property public final long disabledCheckedContentColor;
-    property public final long disabledUncheckedContainerColor;
-    property public final long disabledUncheckedContentColor;
-    property public final long uncheckedContainerColor;
-    property public final long uncheckedContentColor;
-  }
-
   public fun interface TouchExplorationStateProvider {
     method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<java.lang.Boolean> touchExplorationState();
   }
@@ -1296,32 +1405,6 @@
 
 }
 
-package androidx.wear.compose.material3.dialog {
-
-  public final class AlertDialogDefaults {
-    method @androidx.compose.runtime.Composable public void BottomButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public void ConfirmButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public void DismissButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public void GroupSeparator();
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues contentPadding(boolean hasBottomButton);
-    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getConfirmIcon();
-    method public kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> getDismissIcon();
-    method public float getEdgeButtonExtraTopPadding();
-    method public androidx.compose.foundation.layout.Arrangement.Vertical getVerticalArrangement();
-    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> ConfirmIcon;
-    property public final kotlin.jvm.functions.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit> DismissIcon;
-    property public final androidx.compose.foundation.layout.Arrangement.Vertical VerticalArrangement;
-    property public final float edgeButtonExtraTopPadding;
-    field public static final androidx.wear.compose.material3.dialog.AlertDialogDefaults INSTANCE;
-  }
-
-  public final class AlertDialogKt {
-    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> bottomButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
-    method @androidx.compose.runtime.Composable public static void AlertDialog(boolean show, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> confirmButton, kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.ui.window.DialogProperties properties, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
-  }
-
-}
-
 package androidx.wear.compose.material3.lazy {
 
   public final class LazyColumnScrollTransformModifiersKt {
diff --git a/wear/compose/compose-material3/build.gradle b/wear/compose/compose-material3/build.gradle
index f103f85..43171ec 100644
--- a/wear/compose/compose-material3/build.gradle
+++ b/wear/compose/compose-material3/build.gradle
@@ -32,21 +32,22 @@
 }
 
 dependencies {
-    api("androidx.compose.foundation:foundation:1.7.0-rc01")
-    api("androidx.compose.ui:ui:1.7.0-rc01")
-    api("androidx.compose.ui:ui-text:1.7.0-rc01")
-    api("androidx.compose.runtime:runtime:1.7.0-rc01")
+    api("androidx.compose.foundation:foundation:1.7.0")
+    api("androidx.compose.ui:ui:1.7.0")
+    api("androidx.compose.ui:ui-text:1.7.0")
+    api("androidx.compose.runtime:runtime:1.7.0")
     api(project(":wear:compose:compose-foundation"))
 
     implementation(libs.kotlinStdlib)
     implementation(libs.kotlinCoroutinesCore)
-    implementation("androidx.compose.animation:animation:1.7.0-rc01")
-    implementation("androidx.compose.material:material-icons-core:1.7.0-rc01")
-    implementation("androidx.compose.material:material-ripple:1.7.0-rc01")
-    implementation("androidx.compose.ui:ui-util:1.7.0-rc01")
+    implementation("androidx.compose.animation:animation:1.7.0")
+    implementation("androidx.compose.material:material-icons-core:1.7.0")
+    implementation("androidx.compose.material:material-ripple:1.7.0")
+    implementation("androidx.compose.ui:ui-util:1.7.0")
     implementation(project(":wear:compose:compose-material-core"))
     implementation("androidx.profileinstaller:profileinstaller:1.3.1")
     implementation("androidx.graphics:graphics-shapes:1.0.0-beta01")
+    implementation project(':compose:animation:animation-graphics')
 
     androidTestImplementation(project(":compose:ui:ui-test"))
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/dialogs/AlertDialogs.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogs.kt
similarity index 95%
rename from wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/dialogs/AlertDialogs.kt
rename to wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogs.kt
index c71f190..4440425 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/dialogs/AlertDialogs.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogs.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.demos.dialogs
+package androidx.wear.compose.material3.demos
 
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
@@ -38,6 +38,8 @@
 import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
 import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
 import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.material3.AlertDialog
+import androidx.wear.compose.material3.AlertDialogDefaults
 import androidx.wear.compose.material3.Button
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.MaterialTheme
@@ -45,11 +47,9 @@
 import androidx.wear.compose.material3.ScreenScaffold
 import androidx.wear.compose.material3.SwitchButton
 import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.dialog.AlertDialog
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults
-import androidx.wear.compose.material3.samples.dialog.AlertDialogWithBottomButtonSample
-import androidx.wear.compose.material3.samples.dialog.AlertDialogWithConfirmAndDismissSample
-import androidx.wear.compose.material3.samples.dialog.AlertDialogWithContentGroupsSample
+import androidx.wear.compose.material3.samples.AlertDialogWithBottomButtonSample
+import androidx.wear.compose.material3.samples.AlertDialogWithConfirmAndDismissSample
+import androidx.wear.compose.material3.samples.AlertDialogWithContentGroupsSample
 
 val AlertDialogs =
     listOf(
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Confirmations.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Confirmations.kt
new file mode 100644
index 0000000..9233b25
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Confirmations.kt
@@ -0,0 +1,108 @@
+/*
+ * 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.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.material3.Confirmation
+import androidx.wear.compose.material3.ConfirmationDefaults
+import androidx.wear.compose.material3.FilledTonalButton
+import androidx.wear.compose.material3.Icon
+import androidx.wear.compose.material3.MaterialTheme
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.samples.ConfirmationSample
+import androidx.wear.compose.material3.samples.FailureConfirmationSample
+import androidx.wear.compose.material3.samples.LongTextConfirmationSample
+import androidx.wear.compose.material3.samples.SuccessConfirmationSample
+
+val Comfirmations =
+    listOf(
+        ComposableDemo("Generic confirmation") { ConfirmationSample() },
+        ComposableDemo("Long content confirmation") { LongTextConfirmationSample() },
+        ComposableDemo("Success confirmation") { SuccessConfirmationSample() },
+        ComposableDemo("Failure confirmation") { FailureConfirmationSample() },
+        ComposableDemo("Confirmation without text") { ConfirmationWithoutText() },
+        ComposableDemo("Confirmation with custom colors") { ConfirmationWithCustomColors() },
+    )
+
+@Composable
+fun ConfirmationWithoutText() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Show Confirmation") }
+        )
+    }
+
+    Confirmation(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+        curvedText = null
+    ) {
+        Icon(
+            imageVector = Icons.Filled.Add,
+            contentDescription = null,
+            modifier = Modifier.size(ConfirmationDefaults.IconSize).align(Alignment.Center),
+            tint = MaterialTheme.colorScheme.primary
+        )
+    }
+}
+
+@Composable
+fun ConfirmationWithCustomColors() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Show Confirmation") }
+        )
+    }
+
+    Confirmation(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+        colors =
+            ConfirmationDefaults.confirmationColors(
+                iconColor = MaterialTheme.colorScheme.tertiary,
+                iconContainerColor = MaterialTheme.colorScheme.onTertiary,
+                textColor = MaterialTheme.colorScheme.onSurfaceVariant
+            ),
+        curvedText = ConfirmationDefaults.curvedText("Custom confirmation")
+    ) {
+        Icon(
+            imageVector = Icons.Filled.Add,
+            contentDescription = null,
+            modifier = Modifier.size(ConfirmationDefaults.IconSize).align(Alignment.Center),
+        )
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/OpenOnPhoneDialogDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/OpenOnPhoneDialogDemo.kt
new file mode 100644
index 0000000..ab628e5
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/OpenOnPhoneDialogDemo.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.material3.FilledTonalButton
+import androidx.wear.compose.material3.MaterialTheme
+import androidx.wear.compose.material3.OpenOnPhoneDialog
+import androidx.wear.compose.material3.OpenOnPhoneDialogDefaults
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.samples.OpenOnPhoneDialogSample
+
+val OpenOnPhoneDialogDemos =
+    listOf(
+        ComposableDemo("Default OpenOnPhone Dialog") { OpenOnPhoneDialogSample() },
+        ComposableDemo("With custom text") { OpenOnPhoneDialogWithCustomText() },
+        ComposableDemo("With custom colors") { OpenOnPhoneDialogWithCustomColors() },
+    )
+
+@Composable
+fun OpenOnPhoneDialogWithCustomText() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Open on phone") }
+        )
+    }
+
+    OpenOnPhoneDialog(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+        curvedText = OpenOnPhoneDialogDefaults.curvedText("Custom text")
+    )
+}
+
+@Composable
+fun OpenOnPhoneDialogWithCustomColors() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Open on phone") }
+        )
+    }
+
+    OpenOnPhoneDialog(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+        colors =
+            OpenOnPhoneDialogDefaults.colors(
+                iconColor = MaterialTheme.colorScheme.tertiary,
+                iconContainerColor = MaterialTheme.colorScheme.tertiaryContainer,
+                progressIndicatorColor = MaterialTheme.colorScheme.tertiary,
+                progressTrackColor = MaterialTheme.colorScheme.onTertiary,
+                textColor = MaterialTheme.colorScheme.onSurfaceVariant
+            )
+    )
+}
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 082ed2d..2f9ce14 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
@@ -22,7 +22,6 @@
 import androidx.wear.compose.integration.demos.common.Centralize
 import androidx.wear.compose.integration.demos.common.ComposableDemo
 import androidx.wear.compose.integration.demos.common.Material3DemoCategory
-import androidx.wear.compose.material3.demos.dialogs.AlertDialogs
 import androidx.wear.compose.material3.samples.AnimatedTextSample
 import androidx.wear.compose.material3.samples.AnimatedTextSampleButtonResponse
 import androidx.wear.compose.material3.samples.AnimatedTextSampleSharedFontRegistry
@@ -46,12 +45,9 @@
         listOf(
             ComposableDemo("Color Scheme") { ColorSchemeDemos() },
             Material3DemoCategory("Curved Text", CurvedTextDemos),
-            Material3DemoCategory(
-                "Dialogs",
-                listOf(
-                    Material3DemoCategory("AlertDialog", AlertDialogs),
-                )
-            ),
+            Material3DemoCategory("Alert Dialog", AlertDialogs),
+            Material3DemoCategory("Confirmation", Comfirmations),
+            Material3DemoCategory("Open on phone Dialog", OpenOnPhoneDialogDemos),
             ComposableDemo("Scaffold") { ScaffoldSample() },
             Material3DemoCategory("ScrollAway", ScrollAwayDemos),
             ComposableDemo("Haptics") { Centralize { HapticsDemos() } },
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/dialog/AlertDialogSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/AlertDialogSample.kt
similarity index 96%
rename from wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/dialog/AlertDialogSample.kt
rename to wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/AlertDialogSample.kt
index e20161b..dae4eef 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/dialog/AlertDialogSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/AlertDialogSample.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.samples.dialog
+package androidx.wear.compose.material3.samples
 
 import androidx.annotation.Sampled
 import androidx.compose.foundation.layout.Box
@@ -31,12 +31,12 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material3.AlertDialog
+import androidx.wear.compose.material3.AlertDialogDefaults
 import androidx.wear.compose.material3.FilledTonalButton
 import androidx.wear.compose.material3.Icon
 import androidx.wear.compose.material3.MaterialTheme
 import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.dialog.AlertDialog
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults
 
 @Sampled
 @Composable
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ConfirmationSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ConfirmationSample.kt
new file mode 100644
index 0000000..46bde32
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ConfirmationSample.kt
@@ -0,0 +1,126 @@
+/*
+ * 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.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.Confirmation
+import androidx.wear.compose.material3.ConfirmationDefaults
+import androidx.wear.compose.material3.FailureConfirmation
+import androidx.wear.compose.material3.FilledTonalButton
+import androidx.wear.compose.material3.Icon
+import androidx.wear.compose.material3.SuccessConfirmation
+import androidx.wear.compose.material3.Text
+
+@Sampled
+@Composable
+fun ConfirmationSample() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Show Confirmation") }
+        )
+    }
+
+    // Has an icon and a short curved text content, which will be displayed along the bottom edge of
+    // the screen.
+    Confirmation(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+        curvedText = ConfirmationDefaults.curvedText("Confirmed")
+    ) {
+        Icon(
+            imageVector = Icons.Filled.Add,
+            contentDescription = null,
+            modifier = Modifier.size(ConfirmationDefaults.IconSize),
+        )
+    }
+}
+
+@Sampled
+@Composable
+fun LongTextConfirmationSample() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Show Confirmation") }
+        )
+    }
+
+    // Has an icon and a text content. Text will be displayed in the center of the screen below the
+    // icon.
+    Confirmation(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+        text = { Text(text = "Your message has been sent") },
+    ) {
+        Icon(
+            imageVector = Icons.Filled.Add,
+            contentDescription = null,
+            modifier = Modifier.size(ConfirmationDefaults.SmallIconSize),
+        )
+    }
+}
+
+@Sampled
+@Composable
+fun FailureConfirmationSample() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Show Confirmation") }
+        )
+    }
+
+    FailureConfirmation(show = showConfirmation, onDismissRequest = { showConfirmation = false })
+}
+
+@Sampled
+@Composable
+fun SuccessConfirmationSample() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Show Confirmation") }
+        )
+    }
+
+    SuccessConfirmation(show = showConfirmation, onDismissRequest = { showConfirmation = false })
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/OpenOnPhoneDialogSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/OpenOnPhoneDialogSample.kt
new file mode 100644
index 0000000..741132e
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/OpenOnPhoneDialogSample.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.FilledTonalButton
+import androidx.wear.compose.material3.OpenOnPhoneDialog
+import androidx.wear.compose.material3.Text
+
+@Sampled
+@Composable
+fun OpenOnPhoneDialogSample() {
+    var showConfirmation by remember { mutableStateOf(false) }
+
+    Box(Modifier.fillMaxSize()) {
+        FilledTonalButton(
+            modifier = Modifier.align(Alignment.Center),
+            onClick = { showConfirmation = true },
+            label = { Text("Open on phone") }
+        )
+    }
+
+    OpenOnPhoneDialog(
+        show = showConfirmation,
+        onDismissRequest = { showConfirmation = false },
+    )
+}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/dialog/AlertDialogScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AlertDialogScreenshotTest.kt
similarity index 95%
rename from wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/dialog/AlertDialogScreenshotTest.kt
rename to wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AlertDialogScreenshotTest.kt
index 0b7d1f8..e049442 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/dialog/AlertDialogScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AlertDialogScreenshotTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.dialog
+package androidx.wear.compose.material3
 
 import android.content.res.Configuration
 import android.os.Build
@@ -41,14 +41,6 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.screenshot.AndroidXScreenshotTestRule
 import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
-import androidx.wear.compose.material3.FilledTonalButton
-import androidx.wear.compose.material3.Icon
-import androidx.wear.compose.material3.SCREENSHOT_GOLDEN_PATH
-import androidx.wear.compose.material3.ScreenSize
-import androidx.wear.compose.material3.TEST_TAG
-import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.goldenIdentifier
-import androidx.wear.compose.material3.setContentWithTheme
 import com.google.testing.junit.testparameterinjector.TestParameter
 import com.google.testing.junit.testparameterinjector.TestParameterInjector
 import org.junit.Rule
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/dialog/AlertDialogTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AlertDialogTest.kt
similarity index 96%
rename from wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/dialog/AlertDialogTest.kt
rename to wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AlertDialogTest.kt
index 14069c6..6e59369 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/dialog/AlertDialogTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AlertDialogTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.dialog
+package androidx.wear.compose.material3
 
 import android.os.Build
 import androidx.compose.foundation.background
@@ -39,17 +39,6 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.test.filters.SdkSuppress
-import androidx.wear.compose.material3.Button
-import androidx.wear.compose.material3.LocalContentColor
-import androidx.wear.compose.material3.LocalTextAlign
-import androidx.wear.compose.material3.LocalTextMaxLines
-import androidx.wear.compose.material3.LocalTextStyle
-import androidx.wear.compose.material3.MaterialTheme
-import androidx.wear.compose.material3.TEST_TAG
-import androidx.wear.compose.material3.TestImage
-import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.setContentWithTheme
-import androidx.wear.compose.material3.setContentWithThemeForSizeAssertions
 import junit.framework.TestCase.assertEquals
 import org.junit.Rule
 import org.junit.Test
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ConfirmationScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ConfirmationScreenshotTest.kt
new file mode 100644
index 0000000..73e047e
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ConfirmationScreenshotTest.kt
@@ -0,0 +1,227 @@
+/*
+ * 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
+
+import android.content.res.Configuration
+import android.os.Build
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.dp
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import androidx.wear.compose.material3.ConfirmationDefaults.curvedText
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(TestParameterInjector::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+class ConfirmationScreenshotTest {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+
+    @get:Rule val testName = TestName()
+
+    @Test
+    fun confirmation_icon_linearText(@TestParameter screenSize: ScreenSize) {
+
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            Confirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                text = { Text("Your message has been sent") }
+            ) {
+                DefaultSmallIcon()
+            }
+        }
+    }
+
+    @Test
+    fun confirmation_icon_curvedText(@TestParameter screenSize: ScreenSize) {
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            Confirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                curvedText = curvedText("Confirmed")
+            ) {
+                DefaultIcon()
+            }
+        }
+    }
+
+    @Test
+    fun confirmation_icon_noText(@TestParameter screenSize: ScreenSize) {
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            Confirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                curvedText = null
+            ) {
+                DefaultIcon()
+            }
+        }
+    }
+
+    @Test
+    fun successConfirmation_icon_text(@TestParameter screenSize: ScreenSize) {
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            SuccessConfirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                curvedText = curvedText("Success")
+            )
+        }
+    }
+
+    @Test
+    fun successConfirmation_icon_noText(@TestParameter screenSize: ScreenSize) {
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            SuccessConfirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                curvedText = null
+            )
+        }
+    }
+
+    @Test
+    fun failureConfirmation_icon_text(@TestParameter screenSize: ScreenSize) {
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            FailureConfirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                curvedText = curvedText("Failure")
+            )
+        }
+    }
+
+    @Test
+    fun failureConfirmation_icon_noText(@TestParameter screenSize: ScreenSize) {
+        rule.verifyConfirmationScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            screenSize = screenSize
+        ) { modifier ->
+            FailureConfirmation(
+                show = true,
+                modifier = modifier,
+                onDismissRequest = {},
+                curvedText = null,
+            )
+        }
+    }
+
+    private fun ComposeContentTestRule.verifyConfirmationScreenshot(
+        testName: TestName,
+        screenshotRule: AndroidXScreenshotTestRule,
+        screenSize: ScreenSize,
+        content: @Composable (modifier: Modifier) -> Unit
+    ) {
+        setContentWithTheme {
+            val originalConfiguration = LocalConfiguration.current
+            val originalContext = LocalContext.current
+            val fixedScreenSizeConfiguration =
+                remember(originalConfiguration) {
+                    Configuration(originalConfiguration).apply {
+                        screenWidthDp = screenSize.size
+                        screenHeightDp = screenSize.size
+                    }
+                }
+            originalContext.resources.configuration.updateFrom(fixedScreenSizeConfiguration)
+
+            CompositionLocalProvider(
+                LocalContext provides originalContext,
+                LocalConfiguration provides fixedScreenSizeConfiguration,
+            ) {
+                content(Modifier.size(screenSize.size.dp).testTag(TEST_TAG))
+            }
+        }
+
+        onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, testName.goldenIdentifier())
+    }
+
+    @Composable
+    private fun DefaultIcon() {
+        Icon(
+            Icons.Filled.Add,
+            modifier = Modifier.size(ConfirmationDefaults.IconSize),
+            tint = MaterialTheme.colorScheme.primary,
+            contentDescription = null
+        )
+    }
+
+    @Composable
+    private fun DefaultSmallIcon() {
+        Icon(
+            Icons.Filled.Add,
+            modifier = Modifier.size(ConfirmationDefaults.SmallIconSize),
+            tint = MaterialTheme.colorScheme.primary,
+            contentDescription = null
+        )
+    }
+}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ConfirmationTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ConfirmationTest.kt
new file mode 100644
index 0000000..31206a1
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ConfirmationTest.kt
@@ -0,0 +1,605 @@
+/*
+ * 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
+
+import android.os.Build
+import androidx.compose.foundation.background
+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.assertIsEqualTo
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.getUnclippedBoundsInRoot
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeRight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.test.filters.SdkSuppress
+import org.junit.Rule
+import org.junit.Test
+
+class ConfirmationTest {
+    @get:Rule val rule = createComposeRule()
+
+    @Test
+    fun confirmation_linearText_supports_testtag() {
+        rule.setContentWithTheme {
+            Confirmation(
+                show = true,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+                text = {},
+            ) {}
+        }
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun confirmation_curvedText_supports_testtag() {
+        rule.setContentWithTheme {
+            Confirmation(
+                show = true,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+                curvedText = {}
+            ) {}
+        }
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun successConfirmation_supports_testtag() {
+        rule.setContentWithTheme {
+            SuccessConfirmation(
+                show = true,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+            )
+        }
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun failureConfirmation_supports_testtag() {
+        rule.setContentWithTheme {
+            FailureConfirmation(
+                show = true,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+            )
+        }
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun confirmation_linearText_supports_swipeToDismiss() {
+        rule.setContentWithTheme {
+            var showDialog by remember { mutableStateOf(true) }
+            Confirmation(
+                modifier = Modifier.testTag(TEST_TAG),
+                text = {},
+                onDismissRequest = { showDialog = false },
+                show = showDialog
+            ) {}
+        }
+
+        rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight() }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun confirmation_curvedText_supports_swipeToDismiss() {
+        rule.setContentWithTheme {
+            var showDialog by remember { mutableStateOf(true) }
+            Confirmation(
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = { showDialog = false },
+                show = showDialog,
+                curvedText = {}
+            ) {}
+        }
+
+        rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight() }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun successConfirmation_supports_swipeToDismiss() {
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            var showDialog by remember { mutableStateOf(true) }
+            SuccessConfirmation(
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = { showDialog = false },
+                show = showDialog,
+            )
+        }
+        // Advancing time so that animation will finish its motion.
+        rule.mainClock.advanceTimeBy(1000)
+        rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight() }
+        rule.mainClock.advanceTimeBy(1000)
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun failureConfirmation_supports_swipeToDismiss() {
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            var showDialog by remember { mutableStateOf(true) }
+            FailureConfirmation(
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = { showDialog = false },
+                show = showDialog,
+            )
+        }
+        // Advancing time so that animation will finish its motion.
+        rule.mainClock.advanceTimeBy(1000)
+        rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight() }
+        rule.mainClock.advanceTimeBy(1000)
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun hides_confirmation_linearText_when_show_false() {
+        rule.setContentWithTheme {
+            Confirmation(
+                show = false,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+                text = {},
+            ) {}
+        }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun hides_confirmation_curvedText_when_show_false() {
+        rule.setContentWithTheme {
+            Confirmation(
+                show = false,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+                curvedText = {}
+            ) {}
+        }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun hides_successConfirmation_when_show_false() {
+        rule.setContentWithTheme {
+            SuccessConfirmation(
+                show = false,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+            )
+        }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun hides_failureConfirmation_when_show_false() {
+        rule.setContentWithTheme {
+            FailureConfirmation(
+                show = false,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+            )
+        }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun confirmation_displays_icon_with_linearText() {
+        rule.setContentWithTheme {
+            Confirmation(
+                text = { Text("Text", modifier = Modifier.testTag(TextTestTag)) },
+                onDismissRequest = {},
+                show = true
+            ) {
+                TestImage(IconTestTag)
+            }
+        }
+        rule.onNodeWithTag(IconTestTag).assertExists()
+        rule.onNodeWithTag(TextTestTag).assertExists()
+    }
+
+    @Test
+    fun confirmation_displays_icon_with_curvedText() {
+        rule.setContentWithTheme {
+            Confirmation(
+                onDismissRequest = {},
+                show = true,
+                curvedText = { curvedText(CurvedText) }
+            ) {
+                TestImage(IconTestTag)
+            }
+        }
+        rule.onNodeWithTag(IconTestTag).assertExists()
+        rule.onNodeWithContentDescription(CurvedText).assertExists()
+    }
+
+    @Test
+    fun successConfirmation_displays_icon_with_text() {
+        rule.setContentWithTheme {
+            SuccessConfirmation(
+                onDismissRequest = {},
+                show = true,
+                curvedText = ConfirmationDefaults.curvedText(CurvedText)
+            ) {
+                TestImage(IconTestTag)
+            }
+        }
+        rule.onNodeWithTag(IconTestTag).assertExists()
+        rule.onNodeWithContentDescription(CurvedText).assertExists()
+    }
+
+    @Test
+    fun failureConfirmation_displays_icon_with_text() {
+        rule.setContentWithTheme {
+            FailureConfirmation(
+                onDismissRequest = {},
+                show = true,
+                curvedText = ConfirmationDefaults.curvedText(CurvedText)
+            ) {
+                TestImage(IconTestTag)
+            }
+        }
+        rule.onNodeWithTag(IconTestTag).assertExists()
+        rule.onNodeWithContentDescription(CurvedText).assertExists()
+    }
+
+    @Test
+    fun confirmation_linearText_dismissed_after_timeout() {
+        var dismissed = false
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            Confirmation(text = {}, onDismissRequest = { dismissed = true }, show = true) {}
+        }
+        // Timeout longer than default confirmation duration
+        rule.mainClock.advanceTimeBy(ConfirmationDefaults.ConfirmationDurationMillis + 1000)
+        assert(dismissed)
+    }
+
+    @Test
+    fun confirmation_curvedText_dismissed_after_timeout() {
+        var dismissed = false
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            Confirmation(onDismissRequest = { dismissed = true }, show = true, curvedText = {}) {}
+        }
+        // Timeout longer than default confirmation duration
+        rule.mainClock.advanceTimeBy(ConfirmationDefaults.ConfirmationDurationMillis + 1000)
+        assert(dismissed)
+    }
+
+    @Test
+    fun successConfirmation_dismissed_after_timeout() {
+        var dismissed = false
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            SuccessConfirmation(
+                onDismissRequest = { dismissed = true },
+                show = true,
+            )
+        }
+        // Timeout longer than default confirmation duration
+        rule.mainClock.advanceTimeBy(ConfirmationDefaults.ConfirmationDurationMillis + 1000)
+        assert(dismissed)
+    }
+
+    @Test
+    fun failureConfirmation_dismissed_after_timeout() {
+        var dismissed = false
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            FailureConfirmation(
+                onDismissRequest = { dismissed = true },
+                show = true,
+            )
+        }
+        // Timeout longer than default confirmation duration
+        rule.mainClock.advanceTimeBy(ConfirmationDefaults.ConfirmationDurationMillis + 1000)
+        assert(dismissed)
+    }
+
+    @Test
+    fun confirmation_linearText_positioning() {
+        rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+            Confirmation(
+                show = true,
+                text = {
+                    Text(
+                        "Title",
+                        modifier = Modifier.testTag(TextTestTag),
+                        textAlign = TextAlign.Center
+                    )
+                },
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+        }
+
+        // Calculating the center of the icon
+        val iconCenter =
+            rule.onNodeWithTag(IconTestTag).getUnclippedBoundsInRoot().run { (top + bottom) / 2 }
+        val textTop = rule.onNodeWithTag(TextTestTag).getUnclippedBoundsInRoot().top
+
+        // Stepping down half of the container height with vertical content padding
+        textTop.assertIsEqualTo(
+            iconCenter +
+                ConfirmationDefaults.ConfirmationIconContainerSmallSize / 2 +
+                ConfirmationDefaults.LinearContentSpacing
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun confirmation_linearText_correct_colors() {
+        var expectedIconColor: Color = Color.Unspecified
+        var expectedIconContainerColor: Color = Color.Unspecified
+        var expectedTextColor: Color = Color.Unspecified
+
+        rule.setContentWithTheme {
+            Confirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+                text = { Text("Text") },
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+            expectedIconColor = MaterialTheme.colorScheme.primary
+            expectedIconContainerColor = MaterialTheme.colorScheme.onPrimary
+            expectedTextColor = MaterialTheme.colorScheme.onBackground
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedIconColor)
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun confirmation_curvedText_correct_colors() {
+        var expectedIconColor: Color = Color.Unspecified
+        var expectedIconContainerColor: Color = Color.Unspecified
+        var expectedTextColor: Color = Color.Unspecified
+        rule.setContentWithTheme {
+            Confirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+                curvedText = ConfirmationDefaults.curvedText(CurvedText)
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+            expectedIconColor = MaterialTheme.colorScheme.primary
+            expectedIconContainerColor = MaterialTheme.colorScheme.onPrimary
+            expectedTextColor = MaterialTheme.colorScheme.onBackground
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedIconColor)
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun successConfirmation_correct_colors() {
+        var expectedIconColor: Color = Color.Unspecified
+        var expectedIconContainerColor: Color = Color.Unspecified
+        var expectedTextColor: Color = Color.Unspecified
+
+        rule.setContentWithTheme {
+            SuccessConfirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+            )
+            expectedIconColor = MaterialTheme.colorScheme.primary
+            expectedIconContainerColor = MaterialTheme.colorScheme.onPrimary
+            expectedTextColor = MaterialTheme.colorScheme.onBackground
+        }
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedIconColor)
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun failureConfirmation_correct_colors() {
+        var expectedIconColor: Color = Color.Unspecified
+        var expectedIconContainerColor: Color = Color.Unspecified
+        var expectedTextColor: Color = Color.Unspecified
+        val backgroundColor = Color.Black
+        rule.setContentWithTheme {
+            FailureConfirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG).background(backgroundColor),
+                show = true,
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+            expectedIconColor = MaterialTheme.colorScheme.errorContainer
+            // As we have .8 alpha, we have to merge this color with background
+            expectedIconContainerColor =
+                MaterialTheme.colorScheme.onErrorContainer.copy(.8f).compositeOver(backgroundColor)
+            expectedTextColor = MaterialTheme.colorScheme.onBackground
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedIconColor)
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun confirmation_linearText_custom_colors() {
+        val customIconColor: Color = Color.Red
+        val customIconContainerColor: Color = Color.Green
+        val customTextColor: Color = Color.Blue
+
+        rule.setContentWithTheme {
+            Confirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+                text = { Text("Text") },
+                colors =
+                    ConfirmationDefaults.confirmationColors(
+                        iconColor = customIconColor,
+                        iconContainerColor = customIconContainerColor,
+                        textColor = customTextColor
+                    )
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun confirmation_curvedText_custom_colors() {
+        val customIconColor: Color = Color.Red
+        val customIconContainerColor: Color = Color.Green
+        val customTextColor: Color = Color.Blue
+
+        rule.setContentWithTheme {
+            Confirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+                colors =
+                    ConfirmationDefaults.confirmationColors(
+                        iconColor = customIconColor,
+                        iconContainerColor = customIconContainerColor,
+                        textColor = customTextColor
+                    ),
+                curvedText = ConfirmationDefaults.curvedText(CurvedText)
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun successConfirmation_curvedText_custom_colors() {
+        val customIconColor: Color = Color.Red
+        val customIconContainerColor: Color = Color.Green
+        val customTextColor: Color = Color.Blue
+
+        rule.setContentWithTheme {
+            SuccessConfirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+                colors =
+                    ConfirmationDefaults.successColors(
+                        iconColor = customIconColor,
+                        iconContainerColor = customIconContainerColor,
+                        textColor = customTextColor
+                    ),
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customTextColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun failureConfirmation_curvedText_custom_colors() {
+        val customIconColor: Color = Color.Red
+        val customIconContainerColor: Color = Color.Green
+        val customTextColor: Color = Color.Blue
+
+        rule.setContentWithTheme {
+            FailureConfirmation(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true,
+                colors =
+                    ConfirmationDefaults.failureColors(
+                        iconColor = customIconColor,
+                        iconContainerColor = customIconContainerColor,
+                        textColor = customTextColor
+                    ),
+            ) {
+                TestIcon(Modifier.testTag(IconTestTag))
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconContainerColor)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customTextColor)
+    }
+}
+
+private const val IconTestTag = "icon"
+private const val TextTestTag = "text"
+private const val CurvedText = "CurvedText"
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 188a8f8..9c0a3f0 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
@@ -618,7 +618,7 @@
     private fun ComposeContentTestRule.verifyIconToggleButtonColors(
         status: Status,
         checked: Boolean,
-        colors: @Composable () -> ToggleButtonColors,
+        colors: @Composable () -> IconToggleButtonColors,
         containerColor: @Composable () -> Color,
         contentColor: @Composable () -> Color,
     ) {
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/OpenOnPhoneDialogScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/OpenOnPhoneDialogScreenshotTest.kt
new file mode 100644
index 0000000..74568a6
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/OpenOnPhoneDialogScreenshotTest.kt
@@ -0,0 +1,110 @@
+/*
+ * 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
+
+import android.content.res.Configuration
+import android.os.Build
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.dp
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(TestParameterInjector::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+class OpenOnPhoneDialogScreenshotTest {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+
+    @get:Rule val testName = TestName()
+
+    @Test
+    fun openOnPhone_50_percent_progress(@TestParameter screenSize: ScreenSize) {
+        rule.verifyOpenOnPhoneScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            advanceTimeBy = OpenOnPhoneDialogDefaults.DurationMillis / 2,
+            screenSize = screenSize
+        )
+    }
+
+    @Test
+    fun openOnPhone_100_percent_progress(@TestParameter screenSize: ScreenSize) {
+        rule.verifyOpenOnPhoneScreenshot(
+            testName = testName,
+            screenshotRule = screenshotRule,
+            advanceTimeBy = OpenOnPhoneDialogDefaults.DurationMillis,
+            screenSize = screenSize
+        )
+    }
+
+    private fun ComposeContentTestRule.verifyOpenOnPhoneScreenshot(
+        testName: TestName,
+        screenshotRule: AndroidXScreenshotTestRule,
+        screenSize: ScreenSize,
+        advanceTimeBy: Long,
+    ) {
+        rule.mainClock.autoAdvance = false
+        setContentWithTheme {
+            val originalConfiguration = LocalConfiguration.current
+            val originalContext = LocalContext.current
+            val fixedScreenSizeConfiguration =
+                remember(originalConfiguration) {
+                    Configuration(originalConfiguration).apply {
+                        screenWidthDp = screenSize.size
+                        screenHeightDp = screenSize.size
+                    }
+                }
+            originalContext.resources.configuration.updateFrom(fixedScreenSizeConfiguration)
+
+            CompositionLocalProvider(
+                LocalContext provides originalContext,
+                LocalConfiguration provides fixedScreenSizeConfiguration,
+            ) {
+                OpenOnPhoneDialog(
+                    show = true,
+                    modifier = Modifier.size(screenSize.size.dp).testTag(TEST_TAG),
+                    onDismissRequest = {},
+                )
+            }
+        }
+
+        rule.mainClock.advanceTimeBy(advanceTimeBy)
+        onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, testName.goldenIdentifier())
+    }
+}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/OpenOnPhoneDialogTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/OpenOnPhoneDialogTest.kt
new file mode 100644
index 0000000..c5de9c1
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/OpenOnPhoneDialogTest.kt
@@ -0,0 +1,176 @@
+/*
+ * 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
+
+import android.os.Build
+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.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeRight
+import androidx.test.filters.SdkSuppress
+import org.junit.Rule
+import org.junit.Test
+
+class OpenOnPhoneDialogTest {
+    @get:Rule val rule = createComposeRule()
+
+    @Test
+    fun openOnPhone_supports_testtag() {
+        rule.setContentWithTheme {
+            OpenOnPhoneDialog(
+                show = true,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+            )
+        }
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun openOnPhone_supports_swipeToDismiss() {
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            var showDialog by remember { mutableStateOf(true) }
+            OpenOnPhoneDialog(
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = { showDialog = false },
+                show = showDialog
+            )
+        }
+        rule.mainClock.advanceTimeBy(OpenOnPhoneDialogDefaults.DurationMillis / 2)
+        rule.onNodeWithTag(TEST_TAG).performTouchInput({ swipeRight() })
+        // Advancing time so that the dialog is dismissed
+        rule.mainClock.advanceTimeBy(300)
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun hides_openOnPhone_when_show_false() {
+        rule.setContentWithTheme {
+            OpenOnPhoneDialog(
+                show = false,
+                modifier = Modifier.testTag(TEST_TAG),
+                onDismissRequest = {},
+            )
+        }
+        rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
+    }
+
+    @Test
+    fun openOnPhone_displays_icon() {
+        rule.setContentWithTheme {
+            OpenOnPhoneDialog(onDismissRequest = {}, show = true) { TestImage(IconTestTag) }
+        }
+        rule.onNodeWithTag(IconTestTag).assertExists()
+    }
+
+    @Test
+    fun openOnPhone_dismissed_after_timeout() {
+        var dismissed = false
+        rule.mainClock.autoAdvance = false
+        rule.setContentWithTheme {
+            OpenOnPhoneDialog(onDismissRequest = { dismissed = true }, show = true) {}
+        }
+        // Timeout longer than default confirmation duration
+        rule.mainClock.advanceTimeBy(OpenOnPhoneDialogDefaults.DurationMillis + 1000)
+        assert(dismissed)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun openOnPhone_correct_colors() {
+        rule.mainClock.autoAdvance = false
+        var expectedIconColor: Color = Color.Unspecified
+        var expectedIconContainerColor: Color = Color.Unspecified
+        var expectedProgressIndicatorColor: Color = Color.Unspecified
+        var expectedProgressTrackColor: Color = Color.Unspecified
+        rule.setContentWithTheme {
+            OpenOnPhoneDialog(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                show = true
+            )
+            expectedIconColor = MaterialTheme.colorScheme.primary
+            expectedIconContainerColor = MaterialTheme.colorScheme.primaryContainer
+            expectedProgressIndicatorColor = MaterialTheme.colorScheme.primary
+            expectedProgressTrackColor = MaterialTheme.colorScheme.onPrimary
+        }
+        // Advance time by half of the default confirmation duration, so that the track and
+        // indicator are shown
+        rule.mainClock.advanceTimeBy(OpenOnPhoneDialogDefaults.DurationMillis / 2)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedIconColor)
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedIconContainerColor)
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedProgressIndicatorColor)
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(expectedProgressTrackColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+    @Test
+    fun openOnPhone_custom_colors() {
+        rule.mainClock.autoAdvance = false
+        val customIconColor: Color = Color.Red
+        val customIconContainerColor: Color = Color.Green
+        val customProgressIndicatorColor: Color = Color.Blue
+        val customProgressTrackColor: Color = Color.Magenta
+        rule.setContentWithTheme {
+            OpenOnPhoneDialog(
+                onDismissRequest = {},
+                modifier = Modifier.testTag(TEST_TAG),
+                colors =
+                    OpenOnPhoneDialogDefaults.colors(
+                        iconColor = customIconColor,
+                        iconContainerColor = customIconContainerColor,
+                        progressIndicatorColor = customProgressIndicatorColor,
+                        progressTrackColor = customProgressTrackColor
+                    ),
+                show = true
+            )
+        }
+        // Advance time by half of the default confirmation duration, so that the track and
+        // indicator are shown
+        rule.mainClock.advanceTimeBy(OpenOnPhoneDialogDefaults.DurationMillis / 2)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconColor)
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customIconContainerColor)
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertContainsColor(customProgressIndicatorColor)
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customProgressTrackColor)
+    }
+}
+
+private const val IconTestTag = "icon"
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 3b9584c..166a54c 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
@@ -611,7 +611,7 @@
     private fun ComposeContentTestRule.verifyTextToggleButtonColors(
         status: Status,
         checked: Boolean,
-        colors: @Composable () -> ToggleButtonColors,
+        colors: @Composable () -> TextToggleButtonColors,
         containerColor: @Composable () -> Color,
         contentColor: @Composable () -> Color,
     ) {
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/dialog/AlertDialog.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AlertDialog.kt
similarity index 92%
rename from wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/dialog/AlertDialog.kt
rename to wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AlertDialog.kt
index 2b34a71..f0cc000 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/dialog/AlertDialog.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AlertDialog.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.dialog
+package androidx.wear.compose.material3
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -46,25 +46,12 @@
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
 import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
-import androidx.wear.compose.material3.Button
-import androidx.wear.compose.material3.ButtonDefaults
-import androidx.wear.compose.material3.EdgeButton
-import androidx.wear.compose.material3.FilledIconButton
-import androidx.wear.compose.material3.FilledTonalIconButton
-import androidx.wear.compose.material3.Icon
-import androidx.wear.compose.material3.LocalContentColor
-import androidx.wear.compose.material3.LocalTextAlign
-import androidx.wear.compose.material3.LocalTextMaxLines
-import androidx.wear.compose.material3.LocalTextStyle
-import androidx.wear.compose.material3.MaterialTheme
-import androidx.wear.compose.material3.PaddingDefaults
-import androidx.wear.compose.material3.ScreenScaffold
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults.bottomSpacing
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults.contentTopSpacing
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults.iconBottomSpacing
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults.textMessageTopSpacing
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults.textPaddingFraction
-import androidx.wear.compose.material3.dialog.AlertDialogDefaults.titlePaddingFraction
+import androidx.wear.compose.material3.AlertDialogDefaults.bottomSpacing
+import androidx.wear.compose.material3.AlertDialogDefaults.contentTopSpacing
+import androidx.wear.compose.material3.AlertDialogDefaults.iconBottomSpacing
+import androidx.wear.compose.material3.AlertDialogDefaults.textMessageTopSpacing
+import androidx.wear.compose.material3.AlertDialogDefaults.textPaddingFraction
+import androidx.wear.compose.material3.AlertDialogDefaults.titlePaddingFraction
 import androidx.wear.compose.materialcore.isSmallScreen
 import androidx.wear.compose.materialcore.screenWidthDp
 
@@ -79,7 +66,7 @@
  *
  * Example of an [AlertDialog] with an icon, title and two buttons to confirm and dismiss:
  *
- * @sample androidx.wear.compose.material3.samples.dialog.AlertDialogWithConfirmAndDismissSample
+ * @sample androidx.wear.compose.material3.samples.AlertDialogWithConfirmAndDismissSample
  * @param show A boolean indicating whether the dialog should be displayed.
  * @param onDismissRequest A lambda function to be called when the dialog is dismissed by swiping
  *   right (typically also called by the [dismissButton]).
@@ -146,11 +133,11 @@
  *
  * Example of an [AlertDialog] with an icon, title, text and bottom [EdgeButton]:
  *
- * @sample androidx.wear.compose.material3.samples.dialog.AlertDialogWithBottomButtonSample
+ * @sample androidx.wear.compose.material3.samples.AlertDialogWithBottomButtonSample
  *
  * Example of an [AlertDialog] with content groups and a bottom [EdgeButton]:
  *
- * @sample androidx.wear.compose.material3.samples.dialog.AlertDialogWithContentGroupsSample
+ * @sample androidx.wear.compose.material3.samples.AlertDialogWithContentGroupsSample
  * @param show A boolean indicating whether the dialog should be displayed.
  * @param onDismissRequest A lambda function to be called when the dialog is dismissed by swiping to
  *   the right or by other dismiss action.
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt
index e6e84b1..ec6ee95a 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt
@@ -220,7 +220,7 @@
     internal var defaultOutlinedIconButtonColorsCached: IconButtonColors? = null
 
     // Icon Toggle Button
-    internal var defaultIconToggleButtonColorsCached: ToggleButtonColors? = null
+    internal var defaultIconToggleButtonColorsCached: IconToggleButtonColors? = null
 
     // Text Button
     internal var defaultTextButtonColorsCached: TextButtonColors? = null
@@ -230,7 +230,7 @@
     internal var defaultOutlinedTextButtonColorsCached: TextButtonColors? = null
 
     // Text Toggle Button
-    internal var defaultTextToggleButtonColorsCached: ToggleButtonColors? = null
+    internal var defaultTextToggleButtonColorsCached: TextToggleButtonColors? = null
 
     // Card
     internal var defaultCardColorsCached: CardColors? = null
@@ -254,6 +254,14 @@
     // Level Indicator
     internal var defaultLevelIndicatorColorsCached: LevelIndicatorColors? = null
 
+    // Confirmation
+    internal var defaultConfirmationColorsCached: ConfirmationColors? = null
+    internal var defaultSuccessConfirmationColorsCached: ConfirmationColors? = null
+    internal var defaultFailureConfirmationColorsCached: ConfirmationColors? = null
+
+    // Open on Phone dialog
+    internal var mDefaultOpenOnPhoneDialogColorsCached: OpenOnPhoneDialogColors? = null
+
     // Picker
     internal var defaultTimePickerColorsCached: TimePickerColors? = null
     internal var defaultDatePickerColorsCached: DatePickerColors? = null
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt
new file mode 100644
index 0000000..e88a30b
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt
@@ -0,0 +1,656 @@
+/*
+ * 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
+
+import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
+import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
+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.graphics.Color
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.platform.LocalAccessibilityManager
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.DialogProperties
+import androidx.wear.compose.foundation.CurvedDirection
+import androidx.wear.compose.foundation.CurvedLayout
+import androidx.wear.compose.foundation.CurvedModifier
+import androidx.wear.compose.foundation.CurvedScope
+import androidx.wear.compose.foundation.CurvedTextStyle
+import androidx.wear.compose.foundation.padding
+import androidx.wear.compose.material3.tokens.ColorSchemeKeyTokens
+import androidx.wear.compose.materialcore.screenHeightDp
+import androidx.wear.compose.materialcore.screenWidthDp
+import kotlinx.coroutines.delay
+
+/**
+ * Shows a [Confirmation] dialog with an icon and optional very short curved text. The length of the
+ * curved text should be very short and should not exceed 1-2 words. If a longer text required, then
+ * another [Confirmation] overload with a column content should be used instead.
+ *
+ * The confirmation will be showing a message to the user for [durationMillis]. After a specified
+ * timeout, the [onDismissRequest] callback will be invoked, where it's up to the caller to handle
+ * the dismissal. To hide the confirmation, [show] parameter should be set to false.
+ *
+ * Example of a [Confirmation] with an icon and a curved text content:
+ *
+ * @sample androidx.wear.compose.material3.samples.ConfirmationSample
+ * @param show A boolean indicating whether the confirmation should be displayed.
+ * @param onDismissRequest A lambda function to be called when the dialog is dismissed - either by
+ *   swiping right or when the [durationMillis] has passed.
+ * @param curvedText A slot for displaying curved text content which will be shown along the bottom
+ *   edge of the dialog.
+ * @param modifier Modifier to be applied to the confirmation content.
+ * @param colors A [ConfirmationColors] object for customizing the colors used in this
+ *   [Confirmation].
+ * @param properties An optional [DialogProperties] object for configuring the dialog's behavior.
+ * @param durationMillis The duration in milliseconds for which the dialog is displayed. Defaults to
+ *   [ConfirmationDefaults.ConfirmationDurationMillis].
+ * @param content A slot for displaying an icon inside the confirmation dialog. It's recommended to
+ *   set its size to [ConfirmationDefaults.IconSize]
+ */
+@Composable
+fun Confirmation(
+    show: Boolean,
+    onDismissRequest: () -> Unit,
+    curvedText: (CurvedScope.() -> Unit)?,
+    modifier: Modifier = Modifier,
+    colors: ConfirmationColors = ConfirmationDefaults.confirmationColors(),
+    properties: DialogProperties = DialogProperties(),
+    durationMillis: Long = ConfirmationDefaults.ConfirmationDurationMillis,
+    content: @Composable BoxScope.() -> Unit
+) {
+    ConfirmationImpl(
+        show = show,
+        onDismissRequest = onDismissRequest,
+        modifier = modifier,
+        iconContainer = confirmationIconContainer(true, colors.iconContainerColor),
+        curvedText = curvedText,
+        colors = colors,
+        properties = properties,
+        durationMillis = durationMillis,
+        content = content
+    )
+}
+
+/**
+ * Shows a [Confirmation] dialog with an icon and optional short text. The length of the text should
+ * not exceed 3 lines. If the text is very short and fits into 1-2 words, consider using another
+ * [Confirmation] overload with curvedContent instead.
+ *
+ * The confirmation will show a message to the user for [durationMillis]. After a specified timeout,
+ * the [onDismissRequest] callback will be invoked, where it's up to the caller to handle the
+ * dismissal. To hide the confirmation, [show] parameter should be set to false.
+ *
+ * Example of a [Confirmation] with an icon and a text which fits into 3 lines:
+ *
+ * @sample androidx.wear.compose.material3.samples.LongTextConfirmationSample
+ * @param show A boolean indicating whether the confirmation should be displayed.
+ * @param onDismissRequest A lambda function to be called when the dialog is dismissed - either by
+ *   swiping right or when the [durationMillis] has passed.
+ * @param text A slot for displaying text below the icon. It should not exceed 3 lines.
+ * @param modifier Modifier to be applied to the confirmation content.
+ * @param colors A [ConfirmationColors] object for customizing the colors used in this
+ *   [Confirmation].
+ * @param properties An optional [DialogProperties] object for configuring the dialog's behavior.
+ * @param durationMillis The duration in milliseconds for which the dialog is displayed. Defaults to
+ *   [ConfirmationDefaults.ConfirmationDurationMillis].
+ * @param content A slot for displaying an icon inside the confirmation dialog, which can be
+ *   animated. It's recommended to set its size to [ConfirmationDefaults.SmallIconSize]
+ */
+@Composable
+fun Confirmation(
+    show: Boolean,
+    onDismissRequest: () -> Unit,
+    text: @Composable (ColumnScope.() -> Unit)?,
+    modifier: Modifier = Modifier,
+    colors: ConfirmationColors = ConfirmationDefaults.confirmationColors(),
+    properties: DialogProperties = DialogProperties(),
+    durationMillis: Long = ConfirmationDefaults.ConfirmationDurationMillis,
+    content: @Composable BoxScope.() -> Unit
+) {
+
+    val a11yDurationMillis =
+        LocalAccessibilityManager.current?.calculateRecommendedTimeoutMillis(
+            originalTimeoutMillis = durationMillis,
+            containsIcons = true,
+            containsText = text != null,
+            containsControls = false,
+        ) ?: durationMillis
+
+    LaunchedEffect(show, a11yDurationMillis) {
+        if (show) {
+            delay(a11yDurationMillis)
+            onDismissRequest()
+        }
+    }
+
+    Dialog(
+        showDialog = show,
+        modifier = modifier,
+        onDismissRequest = onDismissRequest,
+        properties = properties,
+    ) {
+        Box(Modifier.fillMaxSize()) {
+            val horizontalPadding =
+                screenWidthDp().dp * ConfirmationDefaults.HorizontalLinearContentPaddingFraction
+            Column(
+                modifier = Modifier.align(Alignment.Center).padding(horizontal = horizontalPadding),
+                horizontalAlignment = Alignment.CenterHorizontally
+            ) {
+                Box(
+                    modifier = Modifier.align(Alignment.CenterHorizontally),
+                    contentAlignment = Alignment.Center
+                ) {
+                    confirmationIconContainer(false, colors.iconContainerColor)()
+                    CompositionLocalProvider(LocalContentColor provides colors.iconColor) {
+                        content()
+                    }
+                }
+                CompositionLocalProvider(
+                    LocalContentColor provides colors.textColor,
+                    LocalTextStyle provides MaterialTheme.typography.titleMedium,
+                    LocalTextAlign provides TextAlign.Center,
+                    LocalTextMaxLines provides ConfirmationDefaults.LinearContentMaxLines
+                ) {
+                    if (text != null) {
+                        Spacer(Modifier.height(ConfirmationDefaults.LinearContentSpacing))
+                        text()
+                        Spacer(Modifier.height(ConfirmationDefaults.LinearContentSpacing))
+                    }
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Shows a [Confirmation] dialog with a success icon and optional short curved text. This
+ * confirmation indicates a successful operation or action.
+ *
+ * The confirmation will show a message to the user for [durationMillis]. After a specified timeout,
+ * the [onDismissRequest] callback will be invoked, where it's up to the caller to handle the
+ * dismissal. To hide the confirmation, [show] parameter should be set to false.
+ *
+ * Example of a [SuccessConfirmation] usage:
+ *
+ * @sample androidx.wear.compose.material3.samples.SuccessConfirmationSample
+ * @param show A boolean indicating whether the confirmation should be displayed.
+ * @param onDismissRequest A lambda function to be called when the dialog is dismissed - either by
+ *   swiping right or when the [durationMillis] has passed.
+ * @param modifier Modifier to be applied to the confirmation content.
+ * @param curvedText A slot for displaying curved text content which will be shown along the bottom
+ *   edge of the dialog. Defaults to a localized success message.
+ * @param colors A [ConfirmationColors] object for customizing the colors used in this
+ *   [SuccessConfirmation].
+ * @param properties An optional [DialogProperties] object for configuring the dialog's behavior.
+ * @param durationMillis The duration in milliseconds for which the dialog is displayed. Defaults to
+ *   [ConfirmationDefaults.ConfirmationDurationMillis].
+ * @param content A slot for displaying an icon inside the confirmation dialog, which can be
+ *   animated. Defaults to an animated [ConfirmationDefaults.SuccessIcon].
+ */
+@Composable
+fun SuccessConfirmation(
+    show: Boolean,
+    onDismissRequest: () -> Unit,
+    modifier: Modifier = Modifier,
+    curvedText: (CurvedScope.() -> Unit)? = ConfirmationDefaults.successText(),
+    colors: ConfirmationColors = ConfirmationDefaults.successColors(),
+    properties: DialogProperties = DialogProperties(),
+    durationMillis: Long = ConfirmationDefaults.ConfirmationDurationMillis,
+    content: @Composable BoxScope.() -> Unit = ConfirmationDefaults.SuccessIcon,
+) {
+    ConfirmationImpl(
+        show = show,
+        onDismissRequest = onDismissRequest,
+        modifier = modifier,
+        content = content,
+        iconContainer = successIconContainer(colors.iconContainerColor),
+        curvedText = curvedText,
+        colors = colors,
+        properties = properties,
+        durationMillis = durationMillis
+    )
+}
+
+/**
+ * Shows a [Confirmation] dialog with a failure icon and an optional short curved text. This
+ * confirmation indicates an unsuccessful operation or action.
+ *
+ * The confirmation will show a message to the user for [durationMillis]. After a specified timeout,
+ * the [onDismissRequest] callback will be invoked, where it's up to the caller to handle the
+ * dismissal. To hide the confirmation, [show] parameter should be set to false.
+ *
+ * Example of a [FailureConfirmation] usage:
+ *
+ * @sample androidx.wear.compose.material3.samples.FailureConfirmationSample
+ * @param show A boolean indicating whether the confirmation should be displayed.
+ * @param onDismissRequest A lambda function to be called when the dialog is dismissed - either by
+ *   swiping right or when the [durationMillis] has passed.
+ * @param modifier Modifier to be applied to the confirmation content.
+ * @param curvedText A slot for displaying curved text content which will be shown along the bottom
+ *   edge of the dialog. Defaults to a localized failure message.
+ * @param colors A [ConfirmationColors] object for customizing the colors used in this
+ *   [FailureConfirmation].
+ * @param properties An optional [DialogProperties] object for configuring the dialog's behavior.
+ * @param durationMillis The duration in milliseconds for which the dialog is displayed. Defaults to
+ *   [ConfirmationDefaults.ConfirmationDurationMillis].
+ * @param content A slot for displaying an icon inside the confirmation dialog, which can be
+ *   animated. Defaults to [ConfirmationDefaults.FailureIcon].
+ */
+@Composable
+fun FailureConfirmation(
+    show: Boolean,
+    onDismissRequest: () -> Unit,
+    modifier: Modifier = Modifier,
+    curvedText: (CurvedScope.() -> Unit)? = ConfirmationDefaults.failureText(),
+    colors: ConfirmationColors = ConfirmationDefaults.failureColors(),
+    properties: DialogProperties = DialogProperties(),
+    durationMillis: Long = ConfirmationDefaults.ConfirmationDurationMillis,
+    content: @Composable BoxScope.() -> Unit = ConfirmationDefaults.FailureIcon,
+) {
+    ConfirmationImpl(
+        show = show,
+        onDismissRequest = onDismissRequest,
+        modifier = modifier,
+        iconContainer = failureIconContainer(colors.iconContainerColor),
+        curvedText = curvedText,
+        colors = colors,
+        properties = properties,
+        durationMillis = durationMillis,
+        content = content
+    )
+}
+
+/** Contains default values used by [Confirmation] composable. */
+object ConfirmationDefaults {
+
+    /**
+     * Returns a lambda to display a curved success message. The success message is retrieved from
+     * the application's string resources.
+     */
+    @Composable
+    fun successText(): CurvedScope.() -> Unit =
+        curvedText(
+            LocalContext.current.resources.getString(R.string.wear_m3c_confirmation_success_message)
+        )
+
+    /**
+     * Returns a lambda to display a curved failure message. The failure message is retrieved from
+     * the application's string resources.
+     */
+    @Composable
+    fun failureText(): CurvedScope.() -> Unit =
+        curvedText(
+            LocalContext.current.resources.getString(R.string.wear_m3c_confirmation_failure_message)
+        )
+
+    /**
+     * A default composable used in [SuccessConfirmation] that displays a success icon with an
+     * animation.
+     */
+    @OptIn(ExperimentalAnimationGraphicsApi::class)
+    val SuccessIcon: @Composable BoxScope.() -> Unit = {
+        val animation = AnimatedImageVector.animatedVectorResource(R.drawable.check_animation)
+        var atEnd by remember { mutableStateOf(false) }
+        LaunchedEffect(Unit) {
+            delay(FailureIconDelay)
+            atEnd = true
+        }
+        Icon(
+            painter = rememberAnimatedVectorPainter(animation, atEnd),
+            contentDescription = null,
+            modifier = Modifier.size(IconSize)
+        )
+    }
+
+    /**
+     * A default composable used in [FailureConfirmation] that displays a failure icon with an
+     * animation.
+     */
+    @OptIn(ExperimentalAnimationGraphicsApi::class)
+    val FailureIcon: @Composable BoxScope.() -> Unit = {
+        val animation = AnimatedImageVector.animatedVectorResource(R.drawable.failure_animation)
+        var atEnd by remember { mutableStateOf(false) }
+        LaunchedEffect(Unit) {
+            delay(FailureIconDelay)
+            atEnd = true
+        }
+        Icon(
+            painter = rememberAnimatedVectorPainter(animation, atEnd),
+            contentDescription = null,
+            modifier = Modifier.size(IconSize)
+        )
+    }
+
+    /**
+     * A default composable that displays text along a curved path, used in [Confirmation].
+     *
+     * @param text The text to display.
+     * @param style The style to apply to the text. Defaults to
+     *   CurvedTextStyle(MaterialTheme.typography.titleLarge).
+     */
+    @Composable
+    fun curvedText(
+        text: String,
+        style: CurvedTextStyle = CurvedTextStyle(MaterialTheme.typography.titleLarge)
+    ): CurvedScope.() -> Unit = {
+        curvedText(
+            text = text,
+            style = style,
+            maxSweepAngle = CurvedTextDefaults.StaticContentMaxSweepAngle,
+            modifier = CurvedModifier.padding(PaddingDefaults.edgePadding),
+            angularDirection = CurvedDirection.Angular.Reversed
+        )
+    }
+
+    /**
+     * Creates a [ConfirmationColors] that represents the default colors used in a [Confirmation].
+     */
+    @Composable fun confirmationColors() = MaterialTheme.colorScheme.defaultConfirmationColors
+
+    /**
+     * Creates a [ConfirmationColors] with modified colors used in [Confirmation].
+     *
+     * @param iconColor The icon color.
+     * @param iconContainerColor The icon container color.
+     * @param textColor The text color.
+     */
+    @Composable
+    fun confirmationColors(
+        iconColor: Color = Color.Unspecified,
+        iconContainerColor: Color = Color.Unspecified,
+        textColor: Color = Color.Unspecified,
+    ) =
+        MaterialTheme.colorScheme.defaultConfirmationColors.copy(
+            iconColor = iconColor,
+            iconContainerColor = iconContainerColor,
+            textColor = textColor,
+        )
+
+    /**
+     * Creates a [ConfirmationColors] that represents the default colors used in a
+     * [SuccessConfirmation].
+     */
+    @Composable fun successColors() = MaterialTheme.colorScheme.defaultSuccessConfirmationColors
+
+    /**
+     * Creates a [ConfirmationColors] with modified colors used in [SuccessConfirmation].
+     *
+     * @param iconColor The icon color.
+     * @param iconContainerColor The icon container color.
+     * @param textColor The text color.
+     */
+    @Composable
+    fun successColors(
+        iconColor: Color = Color.Unspecified,
+        iconContainerColor: Color = Color.Unspecified,
+        textColor: Color = Color.Unspecified,
+    ) =
+        MaterialTheme.colorScheme.defaultSuccessConfirmationColors.copy(
+            iconColor = iconColor,
+            iconContainerColor = iconContainerColor,
+            textColor = textColor,
+        )
+
+    /**
+     * Creates a [ConfirmationColors] that represents the default colors used in a
+     * [FailureConfirmation].
+     */
+    @Composable fun failureColors() = MaterialTheme.colorScheme.defaultFailureConfirmationColors
+
+    /**
+     * Creates a [ConfirmationColors] with modified colors used in [FailureConfirmation].
+     *
+     * @param iconColor The icon color.
+     * @param iconContainerColor The icon container color.
+     * @param textColor The text color.
+     */
+    @Composable
+    fun failureColors(
+        iconColor: Color = Color.Unspecified,
+        iconContainerColor: Color = Color.Unspecified,
+        textColor: Color = Color.Unspecified,
+    ) =
+        MaterialTheme.colorScheme.defaultFailureConfirmationColors.copy(
+            iconColor = iconColor,
+            iconContainerColor = iconContainerColor,
+            textColor = textColor,
+        )
+
+    /** Default timeout for the [Confirmation] dialog, in milliseconds. */
+    const val ConfirmationDurationMillis = 4000L
+
+    /** Default icon size for the [Confirmation] with curved content */
+    val IconSize = 52.dp
+
+    /** Default icon size for the [Confirmation] with linear content */
+    val SmallIconSize = 36.dp
+
+    private val ColorScheme.defaultConfirmationColors: ConfirmationColors
+        get() {
+            return defaultConfirmationColorsCached
+                ?: ConfirmationColors(
+                        iconColor = fromToken(ColorSchemeKeyTokens.Primary),
+                        iconContainerColor = fromToken(ColorSchemeKeyTokens.OnPrimary),
+                        textColor = fromToken(ColorSchemeKeyTokens.OnBackground)
+                    )
+                    .also { defaultConfirmationColorsCached = it }
+        }
+
+    private val ColorScheme.defaultSuccessConfirmationColors: ConfirmationColors
+        get() {
+            return defaultSuccessConfirmationColorsCached
+                ?: ConfirmationColors(
+                        iconColor = fromToken(ColorSchemeKeyTokens.Primary),
+                        iconContainerColor = fromToken(ColorSchemeKeyTokens.OnPrimary),
+                        textColor = fromToken(ColorSchemeKeyTokens.OnBackground)
+                    )
+                    .also { defaultSuccessConfirmationColorsCached = it }
+        }
+
+    private val ColorScheme.defaultFailureConfirmationColors: ConfirmationColors
+        get() {
+            return defaultFailureConfirmationColorsCached
+                ?: ConfirmationColors(
+                        iconColor = fromToken(ColorSchemeKeyTokens.ErrorContainer),
+                        iconContainerColor =
+                            fromToken(ColorSchemeKeyTokens.OnErrorContainer).copy(.8f),
+                        textColor = fromToken(ColorSchemeKeyTokens.OnBackground)
+                    )
+                    .also { defaultFailureConfirmationColorsCached = it }
+        }
+
+    internal val FailureIconDelay = 67L
+
+    internal val SuccessWidthFraction = 0.496f
+    internal val SuccessHeightFraction = 0.6f
+    internal val FailureSizeFraction = 0.52f
+
+    internal val ConfirmationIconContainerSmallSize = 80.dp
+    internal val ConfirmationIconContainerSizeFraction = 0.52
+
+    internal val ExtraBottomPaddingFraction = 0.02f
+
+    internal val LinearContentSpacing = 8.dp
+    internal val LinearContentMaxLines = 3
+    internal val HorizontalLinearContentPaddingFraction = 0.12f
+}
+
+/**
+ * Represents the colors used in [Confirmation], [SuccessConfirmation] and [FailureConfirmation].
+ *
+ * @param iconColor Color used to tint the icon.
+ * @param iconContainerColor The color of the container behind the icon.
+ * @param textColor Color used to tint the text.
+ */
+class ConfirmationColors(
+    val iconColor: Color,
+    val iconContainerColor: Color,
+    val textColor: Color,
+) {
+    internal fun copy(
+        iconColor: Color? = null,
+        iconContainerColor: Color? = null,
+        textColor: Color? = null
+    ) =
+        ConfirmationColors(
+            iconColor = iconColor ?: this.iconColor,
+            iconContainerColor = iconContainerColor ?: this.iconContainerColor,
+            textColor = textColor ?: this.textColor,
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is ConfirmationColors) return false
+
+        if (iconColor != other.iconColor) return false
+        if (iconContainerColor != other.iconContainerColor) return false
+        if (textColor != other.textColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = iconColor.hashCode()
+        result = 31 * result + iconContainerColor.hashCode()
+        result = 31 * result + textColor.hashCode()
+        return result
+    }
+}
+
+@Composable
+internal fun ConfirmationImpl(
+    show: Boolean,
+    onDismissRequest: () -> Unit,
+    modifier: Modifier,
+    iconContainer: @Composable BoxScope.() -> Unit,
+    curvedText: (CurvedScope.() -> Unit)?,
+    colors: ConfirmationColors,
+    properties: DialogProperties,
+    durationMillis: Long,
+    content: @Composable BoxScope.() -> Unit
+) {
+    val a11yDurationMillis =
+        LocalAccessibilityManager.current?.calculateRecommendedTimeoutMillis(
+            originalTimeoutMillis = durationMillis,
+            containsIcons = true,
+            containsText = curvedText != null,
+            containsControls = false,
+        ) ?: durationMillis
+
+    LaunchedEffect(show, a11yDurationMillis) {
+        if (show) {
+            delay(a11yDurationMillis)
+            onDismissRequest()
+        }
+    }
+
+    Dialog(
+        showDialog = show,
+        modifier = modifier,
+        onDismissRequest = onDismissRequest,
+        properties = properties,
+    ) {
+        Box(modifier = Modifier.fillMaxSize()) {
+            val bottomPadding =
+                if (curvedText != null)
+                    screenHeightDp() * ConfirmationDefaults.ExtraBottomPaddingFraction
+                else 0f
+            Box(
+                Modifier.fillMaxSize().padding(bottom = bottomPadding.dp),
+                contentAlignment = Alignment.Center
+            ) {
+                iconContainer()
+                CompositionLocalProvider(LocalContentColor provides colors.iconColor) { content() }
+            }
+            CompositionLocalProvider(LocalContentColor provides colors.textColor) {
+                curvedText?.let { CurvedLayout(anchor = 90f, contentBuilder = curvedText) }
+            }
+        }
+    }
+}
+
+private fun confirmationIconContainer(
+    curvedContent: Boolean,
+    color: Color
+): @Composable BoxScope.() -> Unit = {
+    val iconShape =
+        if (curvedContent) MaterialTheme.shapes.extraLarge else MaterialTheme.shapes.large
+    val width =
+        if (curvedContent) {
+            (screenWidthDp() * ConfirmationDefaults.ConfirmationIconContainerSizeFraction).dp
+        } else ConfirmationDefaults.ConfirmationIconContainerSmallSize
+
+    Box(
+        Modifier.size(width)
+            .graphicsLayer {
+                shape = iconShape
+                clip = true
+            }
+            .background(color)
+            .align(Alignment.Center)
+    )
+}
+
+private fun successIconContainer(color: Color): @Composable BoxScope.() -> Unit = {
+    val width = screenWidthDp() * ConfirmationDefaults.SuccessWidthFraction
+    val height = screenWidthDp() * ConfirmationDefaults.SuccessHeightFraction
+    Box(
+        Modifier.size(width.dp, height.dp)
+            .graphicsLayer {
+                rotationZ = 45f
+                shape = CircleShape
+                clip = true
+            }
+            .background(color)
+    )
+}
+
+private fun failureIconContainer(color: Color): @Composable BoxScope.() -> Unit = {
+    val iconShape = MaterialTheme.shapes.extraLarge
+    val width = screenWidthDp() * ConfirmationDefaults.FailureSizeFraction
+    Box(
+        Modifier.size(width.dp)
+            .graphicsLayer {
+                shape = iconShape
+                clip = true
+            }
+            .background(color)
+    )
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/dialog/Dialog.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt
similarity index 97%
rename from wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/dialog/Dialog.kt
rename to wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt
index d42ba2d..f5c6dc6 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/dialog/Dialog.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.dialog
+package androidx.wear.compose.material3
 
 import androidx.compose.animation.core.MutableTransitionState
 import androidx.compose.animation.core.Transition
@@ -34,9 +34,6 @@
 import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.window.DialogProperties
 import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
-import androidx.wear.compose.material3.MaterialTheme
-import androidx.wear.compose.material3.ScreenScaffold
-import androidx.wear.compose.material3.SwipeToDismissBox
 import androidx.wear.compose.material3.tokens.MotionTokens
 
 /**
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt
index 7f89966..1d4e8e4 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt
@@ -16,6 +16,8 @@
 
 package androidx.wear.compose.material3
 
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.tween
 import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.interaction.Interaction
 import androidx.compose.foundation.interaction.InteractionSource
@@ -27,6 +29,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
+import androidx.compose.runtime.State
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
@@ -37,8 +40,10 @@
 import androidx.wear.compose.material3.tokens.FilledTonalIconButtonTokens
 import androidx.wear.compose.material3.tokens.IconButtonTokens
 import androidx.wear.compose.material3.tokens.IconToggleButtonTokens
+import androidx.wear.compose.material3.tokens.MotionTokens
 import androidx.wear.compose.material3.tokens.OutlinedIconButtonTokens
 import androidx.wear.compose.material3.tokens.ShapeTokens
+import androidx.wear.compose.materialcore.animateSelectionColor
 
 /**
  * Wear Material [IconButton] is a circular, icon-only button with transparent background and no
@@ -355,8 +360,8 @@
  * @param modifier Modifier to be applied to the toggle button.
  * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
  *   will not be clickable.
- * @param colors [ToggleButtonColors] that will be used to resolve the container and content color
- *   for this toggle button.
+ * @param colors [IconToggleButtonColors] that will be used to resolve the container and content
+ *   color for this toggle button.
  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
  *   emitting [Interaction]s for this button. You can use this to change the button's appearance or
  *   preview the button in different states. Note that if `null` is provided, interactions will
@@ -372,7 +377,7 @@
     onCheckedChange: (Boolean) -> Unit,
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
-    colors: ToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(),
+    colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(),
     interactionSource: MutableInteractionSource? = null,
     shape: Shape = IconButtonDefaults.shape,
     border: BorderStroke? = null,
@@ -606,7 +611,7 @@
         )
 
     /**
-     * Creates a [ToggleButtonColors] for a [IconToggleButton]
+     * Creates an [IconToggleButtonColors] for a [IconToggleButton]
      * - by default, a colored background with a contrasting content color.
      *
      * If the button is disabled, then the colors will have an alpha ([DisabledContentAlpha] and
@@ -616,7 +621,7 @@
     fun iconToggleButtonColors() = MaterialTheme.colorScheme.defaultIconToggleButtonColors
 
     /**
-     * Creates a [ToggleButtonColors] for a [IconToggleButton]
+     * Creates a [IconToggleButtonColors] for a [IconToggleButton]
      * - by default, a colored background with a contrasting content color.
      *
      * If the button is disabled, then the colors will have an alpha ([DisabledContentAlpha] and
@@ -649,7 +654,7 @@
         disabledCheckedContentColor: Color = Color.Unspecified,
         disabledUncheckedContainerColor: Color = Color.Unspecified,
         disabledUncheckedContentColor: Color = Color.Unspecified,
-    ): ToggleButtonColors =
+    ): IconToggleButtonColors =
         MaterialTheme.colorScheme.defaultIconToggleButtonColors.copy(
             checkedContainerColor = checkedContainerColor,
             checkedContentColor = checkedContentColor,
@@ -797,10 +802,10 @@
                     .also { defaultIconButtonColorsCached = it }
         }
 
-    private val ColorScheme.defaultIconToggleButtonColors: ToggleButtonColors
+    private val ColorScheme.defaultIconToggleButtonColors: IconToggleButtonColors
         get() {
             return defaultIconToggleButtonColorsCached
-                ?: ToggleButtonColors(
+                ?: IconToggleButtonColors(
                         checkedContainerColor =
                             fromToken(IconToggleButtonTokens.CheckedContainerColor),
                         checkedContentColor = fromToken(IconToggleButtonTokens.CheckedContentColor),
@@ -914,3 +919,129 @@
         return result
     }
 }
+
+/**
+ * Represents the different container and content colors used for [IconToggleButton] in various
+ * states, that are checked, unchecked, enabled and disabled.
+ *
+ * @param checkedContainerColor Container or background color when the toggle button is checked
+ * @param checkedContentColor Color of the content (text or icon) when the toggle button is checked
+ * @param uncheckedContainerColor Container or background color when the toggle button is unchecked
+ * @param uncheckedContentColor Color of the content (text or icon) when the toggle button is
+ *   unchecked
+ * @param disabledCheckedContainerColor Container or background color when the toggle button is
+ *   disabled and checked
+ * @param disabledCheckedContentColor Color of content (text or icon) when the toggle button is
+ *   disabled and checked
+ * @param disabledUncheckedContainerColor Container or background color when the toggle button is
+ *   disabled and unchecked
+ * @param disabledUncheckedContentColor Color of the content (text or icon) when the toggle button
+ *   is disabled and unchecked
+ */
+@Immutable
+class IconToggleButtonColors(
+    val checkedContainerColor: Color,
+    val checkedContentColor: Color,
+    val uncheckedContainerColor: Color,
+    val uncheckedContentColor: Color,
+    val disabledCheckedContainerColor: Color,
+    val disabledCheckedContentColor: Color,
+    val disabledUncheckedContainerColor: Color,
+    val disabledUncheckedContentColor: Color,
+) {
+    internal fun copy(
+        checkedContainerColor: Color,
+        checkedContentColor: Color,
+        uncheckedContainerColor: Color,
+        uncheckedContentColor: Color,
+        disabledCheckedContainerColor: Color,
+        disabledCheckedContentColor: Color,
+        disabledUncheckedContainerColor: Color,
+        disabledUncheckedContentColor: Color,
+    ): IconToggleButtonColors =
+        IconToggleButtonColors(
+            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+            uncheckedContainerColor =
+                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+            disabledCheckedContainerColor =
+                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+            disabledCheckedContentColor =
+                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+            disabledUncheckedContainerColor =
+                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+            disabledUncheckedContentColor =
+                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+        )
+
+    /**
+     * Determines the container color based on whether the toggle button is [enabled] and [checked].
+     *
+     * @param enabled Whether the toggle button is enabled
+     * @param checked Whether the toggle button is checked
+     */
+    @Composable
+    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContainerColor,
+            uncheckedColor = uncheckedContainerColor,
+            disabledCheckedColor = disabledCheckedContainerColor,
+            disabledUncheckedColor = disabledUncheckedContainerColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Determines the content color based on whether the toggle button is [enabled] and [checked].
+     *
+     * @param enabled Whether the toggle button is enabled
+     * @param checked Whether the toggle button is checked
+     */
+    @Composable
+    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContentColor,
+            uncheckedColor = uncheckedContentColor,
+            disabledCheckedColor = disabledCheckedContentColor,
+            disabledUncheckedColor = disabledUncheckedContentColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null) return false
+        if (this::class != other::class) return false
+
+        other as IconToggleButtonColors
+
+        if (checkedContainerColor != other.checkedContainerColor) return false
+        if (checkedContentColor != other.checkedContentColor) return false
+        if (uncheckedContainerColor != other.uncheckedContainerColor) return false
+        if (uncheckedContentColor != other.uncheckedContentColor) return false
+        if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
+        if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
+        if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
+        if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = checkedContainerColor.hashCode()
+        result = 31 * result + checkedContentColor.hashCode()
+        result = 31 * result + uncheckedContainerColor.hashCode()
+        result = 31 * result + uncheckedContentColor.hashCode()
+        result = 31 * result + disabledCheckedContainerColor.hashCode()
+        result = 31 * result + disabledCheckedContentColor.hashCode()
+        result = 31 * result + disabledUncheckedContainerColor.hashCode()
+        result = 31 * result + disabledUncheckedContentColor.hashCode()
+        return result
+    }
+}
+
+private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
+    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt
new file mode 100644
index 0000000..c7944ef
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt
@@ -0,0 +1,338 @@
+/*
+ * 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
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
+import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+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.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.platform.LocalAccessibilityManager
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.DialogProperties
+import androidx.wear.compose.foundation.CurvedDirection
+import androidx.wear.compose.foundation.CurvedLayout
+import androidx.wear.compose.foundation.CurvedModifier
+import androidx.wear.compose.foundation.CurvedScope
+import androidx.wear.compose.foundation.CurvedTextStyle
+import androidx.wear.compose.foundation.padding
+import androidx.wear.compose.material3.tokens.ColorSchemeKeyTokens
+import androidx.wear.compose.materialcore.screenHeightDp
+import androidx.wear.compose.materialcore.screenWidthDp
+import kotlinx.coroutines.delay
+
+/**
+ * A full-screen dialog that displays an animated icon with a curved text at the bottom.
+ *
+ * The dialog will be showing a message to the user for [durationMillis]. After a specified timeout,
+ * the [onDismissRequest] callback will be invoked, where it's up to the caller to handle the
+ * dismissal. To hide the dialog, [show] parameter should be set to false.
+ *
+ * This dialog is typically used to indicate that an action has been initiated and will continue on
+ * the user's phone. Once this dialog is displayed, it's developer responsibility to establish the
+ * connection between the watch and the phone.
+ *
+ * Example of an [OpenOnPhoneDialog] usage:
+ *
+ * @sample androidx.wear.compose.material3.samples.OpenOnPhoneDialogSample
+ * @param show A boolean indicating whether the dialog should be displayed.
+ * @param onDismissRequest A lambda function to be called when the dialog is dismissed - either by
+ *   swiping right or when the [durationMillis] has passed.
+ * @param modifier Modifier to be applied to the dialog content.
+ * @param curvedText A slot for displaying curved text content which will be shown along the bottom
+ *   edge of the dialog. Defaults to a localized open on phone message.
+ * @param colors [OpenOnPhoneDialogColors] that will be used to resolve the colors used for this
+ *   [OpenOnPhoneDialog].
+ * @param properties An optional [DialogProperties] object for configuring the dialog's behavior.
+ * @param durationMillis The duration in milliseconds for which the dialog is displayed. Defaults to
+ *   [OpenOnPhoneDialogDefaults.DurationMillis].
+ * @param content A slot for displaying an icon inside the open on phone dialog, which can be
+ *   animated. Defaults to [OpenOnPhoneDialogDefaults.Icon].
+ */
+@Composable
+fun OpenOnPhoneDialog(
+    show: Boolean,
+    onDismissRequest: () -> Unit,
+    modifier: Modifier = Modifier,
+    curvedText: (CurvedScope.() -> Unit)? = OpenOnPhoneDialogDefaults.curvedText(),
+    colors: OpenOnPhoneDialogColors = OpenOnPhoneDialogDefaults.colors(),
+    properties: DialogProperties = DialogProperties(),
+    durationMillis: Long = OpenOnPhoneDialogDefaults.DurationMillis,
+    content: @Composable BoxScope.() -> Unit = OpenOnPhoneDialogDefaults.Icon,
+) {
+    var progress by remember(show) { mutableFloatStateOf(0f) }
+    val animatable = remember { Animatable(0f) }
+
+    val a11yDurationMillis =
+        LocalAccessibilityManager.current?.calculateRecommendedTimeoutMillis(
+            originalTimeoutMillis = durationMillis,
+            containsIcons = true,
+            containsText = curvedText != null,
+            containsControls = false,
+        ) ?: durationMillis
+
+    LaunchedEffect(show, a11yDurationMillis) {
+        if (show) {
+            animatable.snapTo(0f)
+            animatable.animateTo(
+                targetValue = 1f,
+                animationSpec =
+                    tween(durationMillis = a11yDurationMillis.toInt(), easing = LinearEasing),
+            ) {
+                progress = value
+            }
+            onDismissRequest()
+        }
+    }
+
+    Dialog(
+        showDialog = show,
+        modifier = modifier,
+        onDismissRequest = onDismissRequest,
+        properties = properties,
+    ) {
+        Box(modifier = Modifier.fillMaxSize()) {
+            val bottomPadding =
+                if (curvedText != null)
+                    screenHeightDp() * OpenOnPhoneDialogDefaults.ExtraBottomPaddingFraction
+                else 0f
+            Box(
+                Modifier.fillMaxSize().padding(bottom = bottomPadding.dp),
+                contentAlignment = Alignment.Center
+            ) {
+                iconContainer(
+                    iconContainerColor = colors.iconContainerColor,
+                    progressIndicatorColors =
+                        ProgressIndicatorColors(
+                            SolidColor(colors.progressIndicatorColor),
+                            SolidColor(colors.progressTrackColor)
+                        ),
+                    progress = { progress }
+                )()
+                CompositionLocalProvider(LocalContentColor provides colors.iconColor) { content() }
+            }
+            CompositionLocalProvider(LocalContentColor provides colors.textColor) {
+                curvedText?.let { CurvedLayout(anchor = 90f, contentBuilder = curvedText) }
+            }
+        }
+    }
+}
+
+/** Contains the default values used by [OpenOnPhoneDialog]. */
+object OpenOnPhoneDialogDefaults {
+
+    /**
+     * A default composable used in [OpenOnPhoneDialog] that displays an open on phone icon with an
+     * animation.
+     */
+    @OptIn(ExperimentalAnimationGraphicsApi::class)
+    val Icon: @Composable BoxScope.() -> Unit = {
+        val animation =
+            AnimatedImageVector.animatedVectorResource(R.drawable.open_on_phone_animation)
+        var atEnd by remember { mutableStateOf(false) }
+        LaunchedEffect(Unit) {
+            delay(IconDelay)
+            atEnd = true
+        }
+        Icon(
+            painter = rememberAnimatedVectorPainter(animation, atEnd),
+            contentDescription = null,
+            modifier = Modifier.size(IconSize).align(Alignment.Center),
+        )
+    }
+
+    /**
+     * A default composable that displays text along a curved path, used in [OpenOnPhoneDialog].
+     *
+     * @param text The text to display. Defaults to an open on phone message.
+     * @param style The style to apply to the text. Defaults to
+     *   CurvedTextStyle(MaterialTheme.typography.titleLarge).
+     */
+    @Composable
+    fun curvedText(
+        text: String = LocalContext.current.resources.getString(R.string.wear_m3c_open_on_phone),
+        style: CurvedTextStyle = CurvedTextStyle(MaterialTheme.typography.titleLarge)
+    ): CurvedScope.() -> Unit = {
+        curvedText(
+            text = text,
+            style = style,
+            maxSweepAngle = CurvedTextDefaults.StaticContentMaxSweepAngle,
+            modifier = CurvedModifier.padding(PaddingDefaults.edgePadding),
+            angularDirection = CurvedDirection.Angular.Reversed
+        )
+    }
+
+    /**
+     * Creates a [OpenOnPhoneDialogColors] that represents the default colors used in
+     * [OpenOnPhoneDialog].
+     */
+    @Composable fun colors() = MaterialTheme.colorScheme.defaultOpenOnPhoneDialogColors
+
+    /**
+     * Creates a [OpenOnPhoneDialogColors] with modified colors used in [OpenOnPhoneDialog].
+     *
+     * @param iconColor The icon color.
+     * @param iconContainerColor The icon container color.
+     * @param progressIndicatorColor The progress indicator color.
+     * @param progressTrackColor The progress track color.
+     * @param textColor The text color.
+     */
+    @Composable
+    fun colors(
+        iconColor: Color = Color.Unspecified,
+        iconContainerColor: Color = Color.Unspecified,
+        progressIndicatorColor: Color = Color.Unspecified,
+        progressTrackColor: Color = Color.Unspecified,
+        textColor: Color = Color.Unspecified
+    ) =
+        MaterialTheme.colorScheme.defaultOpenOnPhoneDialogColors.copy(
+            iconColor = iconColor,
+            iconContainerColor = iconContainerColor,
+            progressIndicatorColor = progressIndicatorColor,
+            progressTrackColor = progressTrackColor,
+            textColor = textColor
+        )
+
+    /** Default timeout for the [OpenOnPhoneDialog] dialog, in milliseconds. */
+    const val DurationMillis = 4000L
+
+    internal val IconDelay = 67L
+    internal val SizeFraction = 0.6f
+    internal val ExtraBottomPaddingFraction = 0.02f
+    internal val IconSize = 52.dp
+
+    internal val progressIndicatorStrokeWidth = 5.dp
+    internal val progressIndicatorPadding = 5.dp
+
+    private val ColorScheme.defaultOpenOnPhoneDialogColors: OpenOnPhoneDialogColors
+        get() {
+            return mDefaultOpenOnPhoneDialogColorsCached
+                ?: OpenOnPhoneDialogColors(
+                        iconColor = fromToken(ColorSchemeKeyTokens.Primary),
+                        iconContainerColor = fromToken(ColorSchemeKeyTokens.PrimaryContainer),
+                        progressIndicatorColor = fromToken(ColorSchemeKeyTokens.Primary),
+                        progressTrackColor = fromToken(ColorSchemeKeyTokens.OnPrimary),
+                        textColor = fromToken(ColorSchemeKeyTokens.OnBackground)
+                    )
+                    .also { mDefaultOpenOnPhoneDialogColorsCached = it }
+        }
+}
+
+/**
+ * Represents the colors used in [OpenOnPhoneDialog].
+ *
+ * @param iconColor Color used to tint the icon.
+ * @param iconContainerColor The color of the container behind the icon.
+ * @param progressIndicatorColor Color used to draw the indicator arc of progress indicator.
+ * @param progressTrackColor Color used to draw the track of progress indicator.
+ * @param textColor Color used to draw the text.
+ */
+class OpenOnPhoneDialogColors(
+    val iconColor: Color,
+    val iconContainerColor: Color,
+    val progressIndicatorColor: Color,
+    val progressTrackColor: Color,
+    val textColor: Color
+) {
+    internal fun copy(
+        iconColor: Color? = null,
+        iconContainerColor: Color? = null,
+        progressIndicatorColor: Color? = null,
+        progressTrackColor: Color? = null,
+        textColor: Color? = null
+    ) =
+        OpenOnPhoneDialogColors(
+            iconColor = iconColor ?: this.iconColor,
+            iconContainerColor = iconContainerColor ?: this.iconContainerColor,
+            progressIndicatorColor = progressIndicatorColor ?: this.progressIndicatorColor,
+            progressTrackColor = progressTrackColor ?: this.progressTrackColor,
+            textColor = textColor ?: this.textColor
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is OpenOnPhoneDialogColors) return false
+
+        if (iconColor != other.iconColor) return false
+        if (iconContainerColor != other.iconContainerColor) return false
+        if (progressIndicatorColor != other.progressIndicatorColor) return false
+        if (progressTrackColor != other.progressTrackColor) return false
+        if (textColor != other.textColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = iconColor.hashCode()
+        result = 31 * result + iconContainerColor.hashCode()
+        result = 31 * result + progressIndicatorColor.hashCode()
+        result = 31 * result + progressTrackColor.hashCode()
+        result = 31 * result + textColor.hashCode()
+        return result
+    }
+}
+
+private fun iconContainer(
+    iconContainerColor: Color,
+    progressIndicatorColors: ProgressIndicatorColors,
+    progress: () -> Float
+): @Composable BoxScope.() -> Unit = {
+    val size = screenWidthDp() * OpenOnPhoneDialogDefaults.SizeFraction
+    Box(Modifier.size(size.dp)) {
+        Box(
+            Modifier.fillMaxSize()
+                .padding(
+                    OpenOnPhoneDialogDefaults.progressIndicatorStrokeWidth +
+                        OpenOnPhoneDialogDefaults.progressIndicatorPadding
+                )
+                .graphicsLayer {
+                    shape = CircleShape
+                    clip = true
+                }
+                .background(iconContainerColor)
+        )
+
+        CircularProgressIndicator(
+            progress = progress,
+            strokeWidth = OpenOnPhoneDialogDefaults.progressIndicatorStrokeWidth,
+            colors = progressIndicatorColors
+        )
+    }
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt
index c559aa5..20e8047 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt
@@ -16,6 +16,8 @@
 
 package androidx.wear.compose.material3
 
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.tween
 import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.interaction.Interaction
 import androidx.compose.foundation.interaction.InteractionSource
@@ -28,16 +30,19 @@
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.ReadOnlyComposable
 import androidx.compose.runtime.Stable
+import androidx.compose.runtime.State
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.takeOrElse
 import androidx.wear.compose.material3.tokens.FilledTextButtonTokens
 import androidx.wear.compose.material3.tokens.FilledTonalTextButtonTokens
+import androidx.wear.compose.material3.tokens.MotionTokens
 import androidx.wear.compose.material3.tokens.OutlinedTextButtonTokens
 import androidx.wear.compose.material3.tokens.ShapeTokens
 import androidx.wear.compose.material3.tokens.TextButtonTokens
 import androidx.wear.compose.material3.tokens.TextToggleButtonTokens
+import androidx.wear.compose.materialcore.animateSelectionColor
 
 /**
  * Wear Material [TextButton] is a circular, text-only button with transparent background and no
@@ -170,7 +175,7 @@
     onCheckedChange: (Boolean) -> Unit,
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
-    colors: ToggleButtonColors = TextButtonDefaults.textToggleButtonColors(),
+    colors: TextToggleButtonColors = TextButtonDefaults.textToggleButtonColors(),
     interactionSource: MutableInteractionSource? = null,
     shape: Shape = TextButtonDefaults.shape,
     border: BorderStroke? = null,
@@ -398,7 +403,7 @@
         )
 
     /**
-     * Creates a [ToggleButtonColors] for a [TextToggleButton]
+     * Creates a [TextToggleButtonColors] for a [TextToggleButton]
      * - by default, a colored background with a contrasting content color. If the button is
      *   disabled, then the colors will have an alpha ([DisabledContainerAlpha] or
      *   [DisabledContentAlpha]) value applied.
@@ -407,7 +412,7 @@
     fun textToggleButtonColors() = MaterialTheme.colorScheme.defaultTextToggleButtonColors
 
     /**
-     * Creates a [ToggleButtonColors] for a [TextToggleButton]
+     * Creates a [TextToggleButtonColors] for a [TextToggleButton]
      * - by default, a colored background with a contrasting content color. If the button is
      *   disabled, then the colors will have an alpha ([DisabledContainerAlpha] or
      *   [DisabledContentAlpha]) value applied.
@@ -439,7 +444,7 @@
         disabledCheckedContentColor: Color = Color.Unspecified,
         disabledUncheckedContainerColor: Color = Color.Unspecified,
         disabledUncheckedContentColor: Color = Color.Unspecified,
-    ): ToggleButtonColors =
+    ): TextToggleButtonColors =
         MaterialTheme.colorScheme.defaultTextToggleButtonColors.copy(
             checkedContainerColor = checkedContainerColor,
             checkedContentColor = checkedContentColor,
@@ -575,10 +580,10 @@
                     .also { defaultTextButtonColorsCached = it }
         }
 
-    private val ColorScheme.defaultTextToggleButtonColors: ToggleButtonColors
+    private val ColorScheme.defaultTextToggleButtonColors: TextToggleButtonColors
         get() {
             return defaultTextToggleButtonColorsCached
-                ?: ToggleButtonColors(
+                ?: TextToggleButtonColors(
                         checkedContainerColor =
                             fromToken(TextToggleButtonTokens.CheckedContainerColor),
                         checkedContentColor = fromToken(TextToggleButtonTokens.CheckedContentColor),
@@ -691,3 +696,129 @@
         return result
     }
 }
+
+/**
+ * Represents the different container and content colors used for [TextToggleButton] in various
+ * states, that are checked, unchecked, enabled and disabled.
+ *
+ * @param checkedContainerColor Container or background color when the toggle button is checked
+ * @param checkedContentColor Color of the content (text or icon) when the toggle button is checked
+ * @param uncheckedContainerColor Container or background color when the toggle button is unchecked
+ * @param uncheckedContentColor Color of the content (text or icon) when the toggle button is
+ *   unchecked
+ * @param disabledCheckedContainerColor Container or background color when the toggle button is
+ *   disabled and checked
+ * @param disabledCheckedContentColor Color of content (text or icon) when the toggle button is
+ *   disabled and checked
+ * @param disabledUncheckedContainerColor Container or background color when the toggle button is
+ *   disabled and unchecked
+ * @param disabledUncheckedContentColor Color of the content (text or icon) when the toggle button
+ *   is disabled and unchecked
+ */
+@Immutable
+class TextToggleButtonColors(
+    val checkedContainerColor: Color,
+    val checkedContentColor: Color,
+    val uncheckedContainerColor: Color,
+    val uncheckedContentColor: Color,
+    val disabledCheckedContainerColor: Color,
+    val disabledCheckedContentColor: Color,
+    val disabledUncheckedContainerColor: Color,
+    val disabledUncheckedContentColor: Color,
+) {
+    internal fun copy(
+        checkedContainerColor: Color,
+        checkedContentColor: Color,
+        uncheckedContainerColor: Color,
+        uncheckedContentColor: Color,
+        disabledCheckedContainerColor: Color,
+        disabledCheckedContentColor: Color,
+        disabledUncheckedContainerColor: Color,
+        disabledUncheckedContentColor: Color,
+    ): TextToggleButtonColors =
+        TextToggleButtonColors(
+            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+            uncheckedContainerColor =
+                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+            disabledCheckedContainerColor =
+                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+            disabledCheckedContentColor =
+                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+            disabledUncheckedContainerColor =
+                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+            disabledUncheckedContentColor =
+                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+        )
+
+    /**
+     * Determines the container color based on whether the toggle button is [enabled] and [checked].
+     *
+     * @param enabled Whether the toggle button is enabled
+     * @param checked Whether the toggle button is checked
+     */
+    @Composable
+    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContainerColor,
+            uncheckedColor = uncheckedContainerColor,
+            disabledCheckedColor = disabledCheckedContainerColor,
+            disabledUncheckedColor = disabledUncheckedContainerColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Determines the content color based on whether the toggle button is [enabled] and [checked].
+     *
+     * @param enabled Whether the toggle button is enabled
+     * @param checked Whether the toggle button is checked
+     */
+    @Composable
+    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContentColor,
+            uncheckedColor = uncheckedContentColor,
+            disabledCheckedColor = disabledCheckedContentColor,
+            disabledUncheckedColor = disabledUncheckedContentColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null) return false
+        if (this::class != other::class) return false
+
+        other as TextToggleButtonColors
+
+        if (checkedContainerColor != other.checkedContainerColor) return false
+        if (checkedContentColor != other.checkedContentColor) return false
+        if (uncheckedContainerColor != other.uncheckedContainerColor) return false
+        if (uncheckedContentColor != other.uncheckedContentColor) return false
+        if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
+        if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
+        if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
+        if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = checkedContainerColor.hashCode()
+        result = 31 * result + checkedContentColor.hashCode()
+        result = 31 * result + uncheckedContainerColor.hashCode()
+        result = 31 * result + uncheckedContentColor.hashCode()
+        result = 31 * result + disabledCheckedContainerColor.hashCode()
+        result = 31 * result + disabledCheckedContentColor.hashCode()
+        result = 31 * result + disabledUncheckedContainerColor.hashCode()
+        result = 31 * result + disabledUncheckedContentColor.hashCode()
+        return result
+    }
+}
+
+private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
+    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
deleted file mode 100644
index cc9cc49..0000000
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
+++ /dev/null
@@ -1,153 +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.wear.compose.material3
-
-import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.tween
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.State
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.takeOrElse
-import androidx.wear.compose.material3.tokens.MotionTokens
-import androidx.wear.compose.materialcore.animateSelectionColor
-
-/**
- * Represents the different container and content colors used for [IconToggleButton] and
- * [TextToggleButton]) in various states, that are checked, unchecked, enabled and disabled.
- *
- * @param checkedContainerColor Container or background color when the toggle button is checked
- * @param checkedContentColor Color of the content (text or icon) when the toggle button is checked
- * @param uncheckedContainerColor Container or background color when the toggle button is unchecked
- * @param uncheckedContentColor Color of the content (text or icon) when the toggle button is
- *   unchecked
- * @param disabledCheckedContainerColor Container or background color when the toggle button is
- *   disabled and checked
- * @param disabledCheckedContentColor Color of content (text or icon) when the toggle button is
- *   disabled and checked
- * @param disabledUncheckedContainerColor Container or background color when the toggle button is
- *   disabled and unchecked
- * @param disabledUncheckedContentColor Color of the content (text or icon) when the toggle button
- *   is disabled and unchecked
- */
-@Immutable
-class ToggleButtonColors(
-    val checkedContainerColor: Color,
-    val checkedContentColor: Color,
-    val uncheckedContainerColor: Color,
-    val uncheckedContentColor: Color,
-    val disabledCheckedContainerColor: Color,
-    val disabledCheckedContentColor: Color,
-    val disabledUncheckedContainerColor: Color,
-    val disabledUncheckedContentColor: Color,
-) {
-    internal fun copy(
-        checkedContainerColor: Color,
-        checkedContentColor: Color,
-        uncheckedContainerColor: Color,
-        uncheckedContentColor: Color,
-        disabledCheckedContainerColor: Color,
-        disabledCheckedContentColor: Color,
-        disabledUncheckedContainerColor: Color,
-        disabledUncheckedContentColor: Color,
-    ): ToggleButtonColors =
-        ToggleButtonColors(
-            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
-            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
-            uncheckedContainerColor =
-                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
-            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
-            disabledCheckedContainerColor =
-                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
-            disabledCheckedContentColor =
-                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
-            disabledUncheckedContainerColor =
-                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
-            disabledUncheckedContentColor =
-                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
-        )
-
-    /**
-     * Determines the container color based on whether the toggle button is [enabled] and [checked].
-     *
-     * @param enabled Whether the toggle button is enabled
-     * @param checked Whether the toggle button is checked
-     */
-    @Composable
-    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedContainerColor,
-            uncheckedColor = uncheckedContainerColor,
-            disabledCheckedColor = disabledCheckedContainerColor,
-            disabledUncheckedColor = disabledUncheckedContainerColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    /**
-     * Determines the content color based on whether the toggle button is [enabled] and [checked].
-     *
-     * @param enabled Whether the toggle button is enabled
-     * @param checked Whether the toggle button is checked
-     */
-    @Composable
-    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedContentColor,
-            uncheckedColor = uncheckedContentColor,
-            disabledCheckedColor = disabledCheckedContentColor,
-            disabledUncheckedColor = disabledUncheckedContentColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null) return false
-        if (this::class != other::class) return false
-
-        other as ToggleButtonColors
-
-        if (checkedContainerColor != other.checkedContainerColor) return false
-        if (checkedContentColor != other.checkedContentColor) return false
-        if (uncheckedContainerColor != other.uncheckedContainerColor) return false
-        if (uncheckedContentColor != other.uncheckedContentColor) return false
-        if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
-        if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
-        if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
-        if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = checkedContainerColor.hashCode()
-        result = 31 * result + checkedContentColor.hashCode()
-        result = 31 * result + uncheckedContainerColor.hashCode()
-        result = 31 * result + uncheckedContentColor.hashCode()
-        result = 31 * result + disabledCheckedContainerColor.hashCode()
-        result = 31 * result + disabledCheckedContentColor.hashCode()
-        result = 31 * result + disabledUncheckedContainerColor.hashCode()
-        result = 31 * result + disabledUncheckedContentColor.hashCode()
-        return result
-    }
-}
-
-private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
-    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/res/drawable/check_animation.xml b/wear/compose/compose-material3/src/main/res/drawable/check_animation.xml
new file mode 100644
index 0000000..90fd02a
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/res/drawable/check_animation.xml
@@ -0,0 +1,17 @@
+<!--
+  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.
+  -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="300dp" android:width="400dp" android:viewportHeight="300" android:viewportWidth="400"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="200" android:translateY="176" android:scaleX="1.05507" android:scaleY="1.05556"><path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="34" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M-147.5 -20 C-147.5,-20 -51.5,76 -51.5,76 C-51.5,76 151.5,-127 151.5,-127 "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="250" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="10017" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/main/res/drawable/failure_animation.xml b/wear/compose/compose-material3/src/main/res/drawable/failure_animation.xml
new file mode 100644
index 0000000..2c5120b
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/res/drawable/failure_animation.xml
@@ -0,0 +1,17 @@
+<!--
+  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.
+  -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="800dp" android:width="800dp" android:viewportHeight="800" android:viewportWidth="800"><group android:name="_R_G"><group android:name="_R_G_L_2_G" android:translateX="414" android:translateY="398" android:scaleX="10.57" android:scaleY="10.57"><path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#ff8986" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-14.49 17.77 C-14.49,17.77 -14.49,19.61 -14.49,19.61 C-14.49,19.72 -14.45,19.81 -14.38,19.88 C-14.31,19.95 -14.22,19.99 -14.11,19.99 C-14.11,19.99 7.78,19.99 7.78,19.99 C7.88,19.99 7.97,19.95 8.05,19.88 C8.12,19.81 8.15,19.72 8.15,19.61 C8.15,19.61 8.15,17.77 8.15,17.77 C8.15,17.77 -14.49,17.77 -14.49,17.77c  M-14.49 -17.77 C-14.49,-17.77 8.15,-17.77 8.15,-17.77 C8.15,-17.77 8.15,-19.61 8.15,-19.61 C8.15,-19.72 8.12,-19.81 8.05,-19.88 C7.97,-19.95 7.88,-19.99 7.78,-19.99 C7.78,-19.99 -14.11,-19.99 -14.11,-19.99 C-14.22,-19.99 -14.31,-19.95 -14.38,-19.88 C-14.45,-19.81 -14.49,-19.72 -14.49,-19.61 C-14.49,-19.61 -14.49,-17.77 -14.49,-17.77c  M-14.11 23.29 C-15.12,23.29 -15.99,22.93 -16.71,22.21 C-17.43,21.49 -17.79,20.62 -17.79,19.61 C-17.79,19.61 -17.79,-19.61 -17.79,-19.61 C-17.79,-20.62 -17.43,-21.49 -16.71,-22.21 C-15.99,-22.93 -15.12,-23.29 -14.11,-23.29 C-14.11,-23.29 7.78,-23.29 7.78,-23.29 C8.79,-23.29 9.65,-22.93 10.38,-22.21 C11.1,-21.49 11.46,-20.62 11.46,-19.61 C11.46,-19.61 11.46,-13.32 11.46,-13.32 C11.46,-12.86 11.3,-12.46 10.97,-12.13 C10.65,-11.81 10.25,-11.65 9.78,-11.65 C9.31,-11.65 8.91,-11.81 8.59,-12.13 C8.3,-12.46 8.15,-12.86 8.15,-13.32 C8.15,-13.32 8.15,-14.46 8.15,-14.46 C8.15,-14.46 -14.49,-14.46 -14.49,-14.46 C-14.49,-14.46 -14.49,14.46 -14.49,14.46 C-14.49,14.46 8.15,14.46 8.15,14.46 C8.15,14.46 8.15,13.33 8.15,13.33 C8.15,12.86 8.3,12.46 8.59,12.13 C8.91,11.81 9.31,11.65 9.78,11.65 C10.25,11.65 10.65,11.81 10.97,12.13 C11.3,12.46 11.46,12.86 11.46,13.33 C11.46,13.33 11.46,19.61 11.46,19.61 C11.46,20.62 11.1,21.49 10.38,22.21 C9.65,22.93 8.79,23.29 7.78,23.29 C7.78,23.29 -14.11,23.29 -14.11,23.29c "/></group><group android:name="_R_G_L_1_G" android:translateX="400" android:translateY="400"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#003352" android:fillAlpha="1" android:fillType="nonZero" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M52 61 C52,61 179,-67 179,-67 "/><path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#ff8986" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="34" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M52 61 C52,61 179,-67 179,-67 "/></group><group android:name="_R_G_L_0_G" android:translateX="400" android:translateY="400"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#003352" android:fillAlpha="1" android:fillType="nonZero" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M52 -66 C52,-66 177,60 177,60 "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#ff8986" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="35" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M52 -66 C52,-66 177,60 177,60 "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="100" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="267" android:startOffset="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="100" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="267" android:startOffset="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="267" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="267" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="10017" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/main/res/drawable/open_on_phone_animation.xml b/wear/compose/compose-material3/src/main/res/drawable/open_on_phone_animation.xml
new file mode 100644
index 0000000..26c7f42
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/res/drawable/open_on_phone_animation.xml
@@ -0,0 +1,17 @@
+<!--
+  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.
+  -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="800dp" android:width="800dp" android:viewportHeight="800" android:viewportWidth="800"><group android:name="_R_G"><group android:name="_R_G_L_2_G" android:translateX="372" android:translateY="396" android:scaleX="9.86" android:scaleY="9.86"><path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#d3e3fd" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-7.44 23.29 C-8.45,23.29 -9.32,22.93 -10.04,22.21 C-10.76,21.49 -11.13,20.62 -11.13,19.61 C-11.13,19.61 -11.13,8.18 -11.13,8.18 C-11.13,7.71 -10.96,7.31 -10.64,6.99 C-10.31,6.66 -9.91,6.5 -9.45,6.5 C-8.98,6.5 -8.6,6.66 -8.31,6.99 C-7.98,7.31 -7.82,7.71 -7.82,8.18 C-7.82,8.18 -7.82,14.46 -7.82,14.46 C-7.82,14.46 14.82,14.46 14.82,14.46 C14.82,14.46 14.82,-14.46 14.82,-14.46 C14.82,-14.46 -7.82,-14.46 -7.82,-14.46 C-7.82,-14.46 -7.82,-8.18 -7.82,-8.18 C-7.82,-7.71 -7.98,-7.31 -8.31,-6.99 C-8.6,-6.66 -8.98,-6.5 -9.45,-6.5 C-9.91,-6.5 -10.31,-6.66 -10.64,-6.99 C-10.96,-7.31 -11.13,-7.71 -11.13,-8.18 C-11.13,-8.18 -11.13,-19.61 -11.13,-19.61 C-11.13,-20.62 -10.76,-21.49 -10.04,-22.21 C-9.32,-22.93 -8.45,-23.29 -7.44,-23.29 C-7.44,-23.29 14.44,-23.29 14.44,-23.29 C15.45,-23.29 16.32,-22.93 17.04,-22.21 C17.76,-21.49 18.12,-20.62 18.12,-19.61 C18.12,-19.61 18.12,19.61 18.12,19.61 C18.12,20.62 17.76,21.49 17.04,22.21 C16.32,22.93 15.45,23.29 14.44,23.29 C14.44,23.29 -7.44,23.29 -7.44,23.29c  M-7.82 17.77 C-7.82,17.77 -7.82,19.61 -7.82,19.61 C-7.82,19.72 -7.78,19.81 -7.71,19.88 C-7.64,19.95 -7.55,19.99 -7.44,19.99 C-7.44,19.99 14.44,19.99 14.44,19.99 C14.55,19.99 14.64,19.95 14.71,19.88 C14.78,19.81 14.82,19.72 14.82,19.61 C14.82,19.61 14.82,17.77 14.82,17.77 C14.82,17.77 -7.82,17.77 -7.82,17.77c  M-7.82 -17.77 C-7.82,-17.77 14.82,-17.77 14.82,-17.77 C14.82,-17.77 14.82,-19.61 14.82,-19.61 C14.82,-19.72 14.78,-19.81 14.71,-19.88 C14.64,-19.95 14.55,-19.99 14.44,-19.99 C14.44,-19.99 -7.44,-19.99 -7.44,-19.99 C-7.55,-19.99 -7.64,-19.95 -7.71,-19.88 C-7.78,-19.81 -7.82,-19.72 -7.82,-19.61 C-7.82,-19.61 -7.82,-17.77 -7.82,-17.77c "/></group><group android:name="_R_G_L_1_G" android:translateX="370" android:translateY="428" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#003352" android:fillAlpha="1" android:fillType="nonZero" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M-189 -33 C-189,-33 20,-33 20,-33 "/><path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="30" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M-189 -33 C-189,-33 20,-33 20,-33 "/></group><group android:name="_R_G_L_0_G_T_1" android:translateX="180" android:translateY="395" android:scaleY="0"><group android:name="_R_G_L_0_G" android:translateX="-20" android:translateY="33"><path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="32" android:strokeAlpha="1" android:trimPathStart="0.49" android:trimPathEnd="0.51" android:trimPathOffset="0" android:pathData=" M-36 -90 C-36,-90 21,-33 21,-33 C21,-33 -36,24 -36,24 "/></group></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="217" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="217" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 370,428C 370,428 370,428 370,428"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="217" android:startOffset="67" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 370,428C 370,428 412,428 412,428"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="200" android:startOffset="283" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 412,428C 412,428 400,428 400,428"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.55,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathStart" android:duration="133" android:startOffset="0" android:valueFrom="0.49" android:valueTo="0.49" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathStart" android:duration="100" android:startOffset="133" android:valueFrom="0.49" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="133" android:startOffset="0" android:valueFrom="0.51" android:valueTo="0.51" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="100" android:startOffset="133" android:valueFrom="0.51" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_T_1"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 180,395C 180,395 180,395 180,395"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="217" android:startOffset="67" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 180,395C 180,395 432,395 432,395"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.5,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="200" android:startOffset="283" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 432,395C 432,395 420,395 420,395"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.55,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_T_1"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="10017" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
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 d19c450..4951307 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d sekonde</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Tydperk"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Bevestig"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 ee40287..da5ab9c 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d ሰከንዶች</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"ክፍለ ጊዜ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"አረጋግጥ"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 6f65d6e..450227f 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
@@ -45,5 +45,13 @@
       <item quantity="one">ثانية واحدة</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"فترة"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"تأكيد"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 867bba0..178eaa4 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d ছেকেণ্ড</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"পিৰিয়ড"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"নিশ্চিত কৰক"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 43fc687..de43d4f 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d saniyə</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Müddət"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Təsdiq edin"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 7130d77..eca919a 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d sekundi</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Period"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potvrdi"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 1425da3..dc5e832 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
@@ -39,5 +39,13 @@
       <item quantity="other">%d секунды</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Перыяд"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Пацвердзіць"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 a2b7c61..2866f08 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d секунда</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Точка"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Ден"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Месец"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Година"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Потвърждаване"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Напред"</string>
 </resources>
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 b68d6d9..34a09f1 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d সেকেন্ড</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"সময়সীমা"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"কনফার্ম করুন"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 0654f2f..9e53fc8 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d sekundi</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Period"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potvrđivanje"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 cd62e3f..0c19945 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
@@ -36,5 +36,9 @@
       <item quantity="one">%d segon</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Període"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Dia"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Mes"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Any"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirma"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Següent"</string>
 </resources>
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 e8dfcdc..98dc3ea 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
@@ -39,5 +39,13 @@
       <item quantity="one">%d sekunda</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Období"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potvrdit"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 340890b..d1bd436 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d sekunder</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Format"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Bekræft"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 fd7b287..9fdd438 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d Sekunde</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Zeitraum"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Bestätigen"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 b105e52..20374c9 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d δευτερόλεπτο</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Περίοδος"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Επιβεβαίωση"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 b52363a..58982b2 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d second</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Period"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirm"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 37d75e2..fb5c42c 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d Second</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Period"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Day"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Month"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Year"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirm"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Next"</string>
 </resources>
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 b52363a..58982b2 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d second</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Period"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirm"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 b52363a..58982b2 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d second</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Period"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirm"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
diff --git a/wear/compose/compose-material3/src/main/res/values-en-rXC/strings.xml b/wear/compose/compose-material3/src/main/res/values-en-rXC/strings.xml
index ba2dc8b..0bff2a4 100644
--- a/wear/compose/compose-material3/src/main/res/values-en-rXC/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values-en-rXC/strings.xml
@@ -33,5 +33,9 @@
       <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎%d Second‎‏‎‎‏‎</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎Period‎‏‎‎‏‎"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎Day‎‏‎‎‏‎"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎Month‎‏‎‎‏‎"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎Year‎‏‎‎‏‎"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎Confirm‎‏‎‎‏‎"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎Next‎‏‎‎‏‎"</string>
 </resources>
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
new file mode 100644
index 0000000..5dac2b5
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/res/values-es-rUS/strings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wear_m3c_time_picker_hour" msgid="5670838450714030035">"Hora"</string>
+    <string name="wear_m3c_time_picker_minute" msgid="2847700380677127030">"Minuto"</string>
+    <string name="wear_m3c_time_picker_second" msgid="5551916170669814925">"Segundo"</string>
+    <plurals name="wear_m3c_time_picker_hours_content_description" formatted="false" msgid="7688673698789346225">
+      <item quantity="many">%d de horas</item>
+      <item quantity="other">%d horas</item>
+      <item quantity="one">%d hora</item>
+    </plurals>
+    <plurals name="wear_m3c_time_picker_minutes_content_description" formatted="false" msgid="8268405448590438607">
+      <item quantity="many">%d de minutos</item>
+      <item quantity="other">%d minutos</item>
+      <item quantity="one">%d minuto</item>
+    </plurals>
+    <plurals name="wear_m3c_time_picker_seconds_content_description" formatted="false" msgid="1073969431850983434">
+      <item quantity="many">%d de segundos</item>
+      <item quantity="other">%d segundos</item>
+      <item quantity="one">%d segundo</item>
+    </plurals>
+    <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Período"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
+    <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmar"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
+</resources>
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
new file mode 100644
index 0000000..7ed6eed
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/res/values-es/strings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wear_m3c_time_picker_hour" msgid="5670838450714030035">"Hora"</string>
+    <string name="wear_m3c_time_picker_minute" msgid="2847700380677127030">"Minuto"</string>
+    <string name="wear_m3c_time_picker_second" msgid="5551916170669814925">"Segundo"</string>
+    <plurals name="wear_m3c_time_picker_hours_content_description" formatted="false" msgid="7688673698789346225">
+      <item quantity="many">%d horas</item>
+      <item quantity="other">%d horas</item>
+      <item quantity="one">%d hora</item>
+    </plurals>
+    <plurals name="wear_m3c_time_picker_minutes_content_description" formatted="false" msgid="8268405448590438607">
+      <item quantity="many">%d minutos</item>
+      <item quantity="other">%d minutos</item>
+      <item quantity="one">%d minuto</item>
+    </plurals>
+    <plurals name="wear_m3c_time_picker_seconds_content_description" formatted="false" msgid="1073969431850983434">
+      <item quantity="many">%d segundos</item>
+      <item quantity="other">%d segundos</item>
+      <item quantity="one">%d segundo</item>
+    </plurals>
+    <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periodo"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
+    <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmar"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
+</resources>
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 e2ae406..898d4f1 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d sekund</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periood"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Kinnita"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 98f7e97..202e7ee 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d segundo</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Epea"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Berretsi"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 e51ff20..8f9c137 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
@@ -33,5 +33,13 @@
       <item quantity="other">‏‫%d ثانیه</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"مدت زمان"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"تأیید کردن"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 7a0c590..0f0b50b 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d sekunti</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Jakso"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Vahvista"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 e1e9794..cdc3ad5 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d secondes</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Période"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmer"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 97370e0..bdb1f1b 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d secondes</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Période"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmer"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 1f5b0d0..ad5ca33 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d segundo</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Período"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmar"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 cd43c67..b01e9be 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d સેકન્ડ</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"અવધિ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"કન્ફર્મ કરો"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 0d50a66..c861b3af 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
@@ -33,5 +33,9 @@
       <item quantity="other">%d सेकंड</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"समयअवधि"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"दिन"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"महीना"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"साल"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"पुष्टि करें"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"अगला"</string>
 </resources>
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 71b0d59..af212a5 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d sekundi</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Razdoblje"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potvrdi"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 ead4509..2cce16e 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d másodperc</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Időszak"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Megerősítés"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 bfff0c2..cda99db 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d վայրկյան</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Ժամանակահատված"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Հաստատել"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 aba3a73..66a973e 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d Detik</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Jangka waktu"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Konfirmasi"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 1065161..8983c3f 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d sekúndur</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Punktur"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Staðfesta"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 33d9d41..a9566b7 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
@@ -36,5 +36,13 @@
       <item quantity="one">%d secondo</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periodo"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Conferma"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 320aeef..91f1e27 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
@@ -36,5 +36,13 @@
       <item quantity="other">‏‫%d שניות</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"תקופת זמן"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"אישור"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 2b82492..65e9cc7 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d 秒</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"期間"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"日"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"月"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"年"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"確認"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"次へ"</string>
 </resources>
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 f1930fd..4f4734e 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d წამი</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"პერიოდი"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"დღე"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"თვე"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"წელი"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"დადასტურება"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"შემდეგი"</string>
 </resources>
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 0b79463..e0d8b3d 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d секунд</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Кезең"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Растау"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 b302b3b..410a6f2 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d វិនាទី</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"រយៈពេល"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"បញ្ជាក់"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 fe7c9cf..6ae6994 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d ಸೆಕೆಂಡ್‌ಗಳು</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"ಅವಧಿ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"ದೃಢೀಕರಿಸಿ"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 231ff8f5..45f8446 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d초</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"기간"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"확인"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 efbade7..692726e 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d секунд</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Чекит"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Ырастоо"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 8e4a64e..59d2d94 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d ວິນາທີ</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"ໄລຍະເວລາ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"ຢືນຢັນ"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 ad7f022..615054e 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
@@ -39,5 +39,13 @@
       <item quantity="other">%d sekundžių</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Laikotarpis"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Patvirtinti"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 1057111..08f2d2c 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d sekundes</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periods"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Apstiprināt"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 3e57b97..a093425 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d секунди</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Период"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Потврди"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 ff5642f..36d8b54 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d സെക്കൻഡ്</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"കാലയളവ്"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"സ്ഥിരീകരിക്കുക"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 7db8e1c..629e16a 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d секунд</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Хугацаа"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Баталгаажуулах"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 23e9efe..904ad4f 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d सेकंद</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"कालावधी"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"कन्फर्म करा"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 5869290..df4b8c9 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d Saat</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Tempoh"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Sahkan"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 f328281..aa85494 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d စက္ကန့်</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"အချိန်ကာလ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"အတည်ပြုရန်"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 b4fd2e7..0d9dbd3 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d sekund</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periode"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Bekreft"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 b234e16..4f5d479 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d सेकेन्ड</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"अवधि"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"पुष्टि गर्नुहोस्"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 3afe2c9..8561545 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d seconde</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periode"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Bevestigen"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 acf7af8..7701b598 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d ସେକେଣ୍ଡ</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"ଅବଧି"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 80dbbc1..1000cde 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
@@ -33,5 +33,13 @@
       <item quantity="other">%d ਸਕਿੰਟ</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"ਮਿਆਦ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"ਤਸਦੀਕ ਕਰੋ"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 84a021b..5d56d82 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
@@ -39,5 +39,13 @@
       <item quantity="one">%d sekunda</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Kropka"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potwierdź"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 2dcdcbf..77c3710 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d segundos</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Período"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmar"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 9bbdb89..416cbc0 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
@@ -36,5 +36,9 @@
       <item quantity="one">%d segundo</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Período"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Dia"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Mês"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Ano"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmar"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Seguinte"</string>
 </resources>
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 2dcdcbf..77c3710 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d segundos</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Período"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmar"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 a682983b..f9723df 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
@@ -36,5 +36,13 @@
       <item quantity="one">%d secundă</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Perioada"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Confirmă"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 47fb6f8..e01e3c3 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
@@ -39,5 +39,13 @@
       <item quantity="other">%d секунды</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Период"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Подтвердить"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 491d592..6f3d4c6 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
@@ -33,5 +33,13 @@
       <item quantity="other">තත්පර %d</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"කාල පරිච්ඡේදය"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"තහවුරු කරන්න"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 7b45b82..8840530 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
@@ -39,5 +39,13 @@
       <item quantity="one">%d sekunda</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Obdobie"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potvrdiť"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 164b53e..cc79d76 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
@@ -39,5 +39,9 @@
       <item quantity="other">%d sekund</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Pika"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Dan"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Mesec"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Leto"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Potrdi"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Naprej"</string>
 </resources>
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 149c7bb..411d53e 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d sekondë</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Periudha"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Konfirmo"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 decaa24c..661b6d2 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
@@ -36,5 +36,13 @@
       <item quantity="other">%d секунди</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Период"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Потврди"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 33c96f7..b395ba1d 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d sekund</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Punkt"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Bekräfta"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 d1cc257..aad1959 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
@@ -33,5 +33,13 @@
       <item quantity="one">Sekunde %d</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Kipindi"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Thibitisha"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 669314b..aacd3cd 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d வினாடி</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"கால இடைவெளி"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"உறுதிசெய்யும்"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 353d9fc..2374063 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d సెకను</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"వ్యవధి"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"రోజు"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"నెల"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"సంవత్సరం"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"నిర్ధారించండి"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"తర్వాత"</string>
 </resources>
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 3bd9b5c..d1ad793 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d วินาที</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"ระยะเวลา"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"วัน"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"เดือน"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"ปี"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"ยืนยัน"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"ถัดไป"</string>
 </resources>
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 5d1f051..fe20f09 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
@@ -33,5 +33,9 @@
       <item quantity="other">%d na Segundo</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Panahon"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Araw"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Buwan"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Taon"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Kumpirmahin"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Susunod"</string>
 </resources>
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 1a0f669..3ec35be 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d Saniye</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Aralık"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Onayla"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 40e732c..bb037ea 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
@@ -39,5 +39,13 @@
       <item quantity="other">%d секунди</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Період"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Підтвердити"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 f15dacf..6f902ab 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
@@ -33,5 +33,13 @@
       <item quantity="one">‏‫‎%d سیکنڈ</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"وقفہ"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"تصدیق کریں"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 1025cad..4b1121e 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d soniya</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Oraliq"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"Kun"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"Oy"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"Yil"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Tasdiqlash"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"Keyingisi"</string>
 </resources>
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 6d61d00..3b40f28 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d giây</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Khoảng thời gian"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Xác nhận"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 d89158c..14ce25a 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
@@ -33,5 +33,9 @@
       <item quantity="one">%d 秒</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"时段"</string>
+    <string name="wear_m3c_date_picker_day" msgid="8932770593644830235">"日"</string>
+    <string name="wear_m3c_date_picker_month" msgid="5962969526377479136">"月"</string>
+    <string name="wear_m3c_date_picker_year" msgid="4697690064312147449">"年"</string>
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"确认"</string>
+    <string name="wear_m3c_picker_next_button_content_description" msgid="3346011303652897029">"下一个"</string>
 </resources>
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 68bc1b0..0d30e02 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d 秒</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"時段"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"確認"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 067f1dc..3e569a9 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
@@ -33,5 +33,13 @@
       <item quantity="one">%d 秒</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"期間"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"確認"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
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 159343b..43167ed 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
@@ -33,5 +33,13 @@
       <item quantity="other">Imizuzwana engu-%d</item>
     </plurals>
     <string name="wear_m3c_time_picker_period" msgid="5567285614451063120">"Isikhathi"</string>
+    <!-- no translation found for wear_m3c_date_picker_day (8932770593644830235) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_month (5962969526377479136) -->
+    <skip />
+    <!-- no translation found for wear_m3c_date_picker_year (4697690064312147449) -->
+    <skip />
     <string name="wear_m3c_picker_confirm_button_content_description" msgid="8440144719909288057">"Qinisekisa"</string>
+    <!-- no translation found for wear_m3c_picker_next_button_content_description (3346011303652897029) -->
+    <skip />
 </resources>
diff --git a/wear/compose/compose-material3/src/main/res/values/strings.xml b/wear/compose/compose-material3/src/main/res/values/strings.xml
index 213c3ad..868ca2b 100644
--- a/wear/compose/compose-material3/src/main/res/values/strings.xml
+++ b/wear/compose/compose-material3/src/main/res/values/strings.xml
@@ -36,4 +36,8 @@
     <string description="Lets the user know that this picker is to change the value of the year date unit. Appears on the DatePicker component, on top of the year picker. [CHAR_LIMIT=8]" name="wear_m3c_date_picker_year">Year</string>
     <string description="Content description of the confirm button of DatePicker and TimePicker components. It lets the user confirm the date or time selected. [CHAR_LIMIT=NONE]" name="wear_m3c_picker_confirm_button_content_description">Confirm</string>
     <string description="Content description of the next button of DatePicker and TimePicker components. It lets the user to move to the next picker. [CHAR_LIMIT=NONE]" name="wear_m3c_picker_next_button_content_description">Next</string>
-</resources>
\ No newline at end of file
+
+    <string description="A message which is used to indicate that an action failed in a FailureConfirmation [CHAR_LIMIT=12]" name="wear_m3c_confirmation_failure_message">Failed</string>
+    <string description="A message which is used to indicate that an action succeeded in a SuccessConfirmation [CHAR_LIMIT=12]" name="wear_m3c_confirmation_success_message">Success</string>
+    <string description="A message which is used to indicate than the user should continue their action on their phone, used in OpenOnPhone component [CHAR_LIMIT=12]" name="wear_m3c_open_on_phone">Open on phone</string>
+</resources>
diff --git a/wear/compose/compose-navigation/build.gradle b/wear/compose/compose-navigation/build.gradle
index 2e021e1..bb35fa2 100644
--- a/wear/compose/compose-navigation/build.gradle
+++ b/wear/compose/compose-navigation/build.gradle
@@ -31,8 +31,8 @@
 }
 
 dependencies {
-    api("androidx.compose.ui:ui:1.7.0-rc01")
-    api("androidx.compose.runtime:runtime:1.7.0-rc01")
+    api("androidx.compose.ui:ui:1.7.0")
+    api("androidx.compose.runtime:runtime:1.7.0")
     api("androidx.navigation:navigation-runtime:2.6.0")
     api(project(":wear:compose:compose-material"))
     api("androidx.activity:activity-compose:1.7.0")
diff --git a/wear/compose/compose-ui-tooling/build.gradle b/wear/compose/compose-ui-tooling/build.gradle
index d49acb1..5dcfeea 100644
--- a/wear/compose/compose-ui-tooling/build.gradle
+++ b/wear/compose/compose-ui-tooling/build.gradle
@@ -32,7 +32,7 @@
 
 dependencies {
     api("androidx.annotation:annotation:1.8.1")
-    api("androidx.compose.ui:ui-tooling-preview:1.7.0-rc01")
+    api("androidx.compose.ui:ui-tooling-preview:1.7.0")
 
     implementation(libs.kotlinStdlib)
     implementation("androidx.wear:wear-tooling-preview:1.0.0")
diff --git a/window/window-core/api/current.txt b/window/window-core/api/current.txt
index aa7ee82..2c8a4d2 100644
--- a/window/window-core/api/current.txt
+++ b/window/window-core/api/current.txt
@@ -8,39 +8,68 @@
 
 package androidx.window.core.layout {
 
-  public final class WindowHeightSizeClass {
-    field public static final androidx.window.core.layout.WindowHeightSizeClass COMPACT;
-    field public static final androidx.window.core.layout.WindowHeightSizeClass.Companion Companion;
-    field public static final androidx.window.core.layout.WindowHeightSizeClass EXPANDED;
-    field public static final androidx.window.core.layout.WindowHeightSizeClass MEDIUM;
+  @Deprecated public final class WindowHeightSizeClass {
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass COMPACT;
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass.Companion Companion;
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass EXPANDED;
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass MEDIUM;
   }
 
-  public static final class WindowHeightSizeClass.Companion {
+  @Deprecated public static final class WindowHeightSizeClass.Companion {
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getCOMPACT();
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getEXPANDED();
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getMEDIUM();
+    property @Deprecated public androidx.window.core.layout.WindowHeightSizeClass COMPACT;
+    property @Deprecated public androidx.window.core.layout.WindowHeightSizeClass EXPANDED;
+    property @Deprecated public androidx.window.core.layout.WindowHeightSizeClass MEDIUM;
   }
 
   public final class WindowSizeClass {
-    method public static androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
-    method @SuppressCompatibility @androidx.window.core.ExperimentalWindowCoreApi public static androidx.window.core.layout.WindowSizeClass compute(int widthPx, int heightPx, float density);
-    method public androidx.window.core.layout.WindowHeightSizeClass getWindowHeightSizeClass();
-    method public androidx.window.core.layout.WindowWidthSizeClass getWindowWidthSizeClass();
-    property public final androidx.window.core.layout.WindowHeightSizeClass windowHeightSizeClass;
-    property public final androidx.window.core.layout.WindowWidthSizeClass windowWidthSizeClass;
+    ctor public WindowSizeClass(float widthDp, float heightDp);
+    ctor public WindowSizeClass(int minWidthDp, int minHeightDp);
+    method @Deprecated public static androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
+    method public int getMinHeightDp();
+    method public int getMinWidthDp();
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getWindowHeightSizeClass();
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getWindowWidthSizeClass();
+    method public boolean isAtLeast(int widthDp, int heightDp);
+    method public boolean isHeightAtLeast(int heightDp);
+    method public boolean isWidthAtLeast(int widthDp);
+    property public final int minHeightDp;
+    property public final int minWidthDp;
+    property @Deprecated public final androidx.window.core.layout.WindowHeightSizeClass windowHeightSizeClass;
+    property @Deprecated public final androidx.window.core.layout.WindowWidthSizeClass windowWidthSizeClass;
+    field public static final java.util.Set<androidx.window.core.layout.WindowSizeClass> BREAKPOINTS_V1;
     field public static final androidx.window.core.layout.WindowSizeClass.Companion Companion;
+    field public static final int HEIGHT_DP_EXPANDED_LOWER_BOUND = 900; // 0x384
+    field public static final int HEIGHT_DP_MEDIUM_LOWER_BOUND = 480; // 0x1e0
+    field public static final int WIDTH_DP_EXPANDED_LOWER_BOUND = 840; // 0x348
+    field public static final int WIDTH_DP_MEDIUM_LOWER_BOUND = 600; // 0x258
   }
 
   public static final class WindowSizeClass.Companion {
-    method public androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
-    method @SuppressCompatibility @androidx.window.core.ExperimentalWindowCoreApi public androidx.window.core.layout.WindowSizeClass compute(int widthPx, int heightPx, float density);
+    method @Deprecated public androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
   }
 
-  public final class WindowWidthSizeClass {
-    field public static final androidx.window.core.layout.WindowWidthSizeClass COMPACT;
-    field public static final androidx.window.core.layout.WindowWidthSizeClass.Companion Companion;
-    field public static final androidx.window.core.layout.WindowWidthSizeClass EXPANDED;
-    field public static final androidx.window.core.layout.WindowWidthSizeClass MEDIUM;
+  public final class WindowSizeClassSelectors {
+    method public static androidx.window.core.layout.WindowSizeClass computeWindowSizeClass(java.util.Set<androidx.window.core.layout.WindowSizeClass>, int widthDp, int heightDp);
+    method public static androidx.window.core.layout.WindowSizeClass computeWindowSizeClassPreferHeight(java.util.Set<androidx.window.core.layout.WindowSizeClass>, int widthDp, int heightDp);
   }
 
-  public static final class WindowWidthSizeClass.Companion {
+  @Deprecated public final class WindowWidthSizeClass {
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass COMPACT;
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass.Companion Companion;
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass EXPANDED;
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass MEDIUM;
+  }
+
+  @Deprecated public static final class WindowWidthSizeClass.Companion {
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getCOMPACT();
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getEXPANDED();
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getMEDIUM();
+    property @Deprecated public androidx.window.core.layout.WindowWidthSizeClass COMPACT;
+    property @Deprecated public androidx.window.core.layout.WindowWidthSizeClass EXPANDED;
+    property @Deprecated public androidx.window.core.layout.WindowWidthSizeClass MEDIUM;
   }
 
 }
diff --git a/window/window-core/api/restricted_current.txt b/window/window-core/api/restricted_current.txt
index aa7ee82..2c8a4d2 100644
--- a/window/window-core/api/restricted_current.txt
+++ b/window/window-core/api/restricted_current.txt
@@ -8,39 +8,68 @@
 
 package androidx.window.core.layout {
 
-  public final class WindowHeightSizeClass {
-    field public static final androidx.window.core.layout.WindowHeightSizeClass COMPACT;
-    field public static final androidx.window.core.layout.WindowHeightSizeClass.Companion Companion;
-    field public static final androidx.window.core.layout.WindowHeightSizeClass EXPANDED;
-    field public static final androidx.window.core.layout.WindowHeightSizeClass MEDIUM;
+  @Deprecated public final class WindowHeightSizeClass {
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass COMPACT;
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass.Companion Companion;
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass EXPANDED;
+    field @Deprecated public static final androidx.window.core.layout.WindowHeightSizeClass MEDIUM;
   }
 
-  public static final class WindowHeightSizeClass.Companion {
+  @Deprecated public static final class WindowHeightSizeClass.Companion {
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getCOMPACT();
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getEXPANDED();
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getMEDIUM();
+    property @Deprecated public androidx.window.core.layout.WindowHeightSizeClass COMPACT;
+    property @Deprecated public androidx.window.core.layout.WindowHeightSizeClass EXPANDED;
+    property @Deprecated public androidx.window.core.layout.WindowHeightSizeClass MEDIUM;
   }
 
   public final class WindowSizeClass {
-    method public static androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
-    method @SuppressCompatibility @androidx.window.core.ExperimentalWindowCoreApi public static androidx.window.core.layout.WindowSizeClass compute(int widthPx, int heightPx, float density);
-    method public androidx.window.core.layout.WindowHeightSizeClass getWindowHeightSizeClass();
-    method public androidx.window.core.layout.WindowWidthSizeClass getWindowWidthSizeClass();
-    property public final androidx.window.core.layout.WindowHeightSizeClass windowHeightSizeClass;
-    property public final androidx.window.core.layout.WindowWidthSizeClass windowWidthSizeClass;
+    ctor public WindowSizeClass(float widthDp, float heightDp);
+    ctor public WindowSizeClass(int minWidthDp, int minHeightDp);
+    method @Deprecated public static androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
+    method public int getMinHeightDp();
+    method public int getMinWidthDp();
+    method @Deprecated public androidx.window.core.layout.WindowHeightSizeClass getWindowHeightSizeClass();
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getWindowWidthSizeClass();
+    method public boolean isAtLeast(int widthDp, int heightDp);
+    method public boolean isHeightAtLeast(int heightDp);
+    method public boolean isWidthAtLeast(int widthDp);
+    property public final int minHeightDp;
+    property public final int minWidthDp;
+    property @Deprecated public final androidx.window.core.layout.WindowHeightSizeClass windowHeightSizeClass;
+    property @Deprecated public final androidx.window.core.layout.WindowWidthSizeClass windowWidthSizeClass;
+    field public static final java.util.Set<androidx.window.core.layout.WindowSizeClass> BREAKPOINTS_V1;
     field public static final androidx.window.core.layout.WindowSizeClass.Companion Companion;
+    field public static final int HEIGHT_DP_EXPANDED_LOWER_BOUND = 900; // 0x384
+    field public static final int HEIGHT_DP_MEDIUM_LOWER_BOUND = 480; // 0x1e0
+    field public static final int WIDTH_DP_EXPANDED_LOWER_BOUND = 840; // 0x348
+    field public static final int WIDTH_DP_MEDIUM_LOWER_BOUND = 600; // 0x258
   }
 
   public static final class WindowSizeClass.Companion {
-    method public androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
-    method @SuppressCompatibility @androidx.window.core.ExperimentalWindowCoreApi public androidx.window.core.layout.WindowSizeClass compute(int widthPx, int heightPx, float density);
+    method @Deprecated public androidx.window.core.layout.WindowSizeClass compute(float dpWidth, float dpHeight);
   }
 
-  public final class WindowWidthSizeClass {
-    field public static final androidx.window.core.layout.WindowWidthSizeClass COMPACT;
-    field public static final androidx.window.core.layout.WindowWidthSizeClass.Companion Companion;
-    field public static final androidx.window.core.layout.WindowWidthSizeClass EXPANDED;
-    field public static final androidx.window.core.layout.WindowWidthSizeClass MEDIUM;
+  public final class WindowSizeClassSelectors {
+    method public static androidx.window.core.layout.WindowSizeClass computeWindowSizeClass(java.util.Set<androidx.window.core.layout.WindowSizeClass>, int widthDp, int heightDp);
+    method public static androidx.window.core.layout.WindowSizeClass computeWindowSizeClassPreferHeight(java.util.Set<androidx.window.core.layout.WindowSizeClass>, int widthDp, int heightDp);
   }
 
-  public static final class WindowWidthSizeClass.Companion {
+  @Deprecated public final class WindowWidthSizeClass {
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass COMPACT;
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass.Companion Companion;
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass EXPANDED;
+    field @Deprecated public static final androidx.window.core.layout.WindowWidthSizeClass MEDIUM;
+  }
+
+  @Deprecated public static final class WindowWidthSizeClass.Companion {
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getCOMPACT();
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getEXPANDED();
+    method @Deprecated public androidx.window.core.layout.WindowWidthSizeClass getMEDIUM();
+    property @Deprecated public androidx.window.core.layout.WindowWidthSizeClass COMPACT;
+    property @Deprecated public androidx.window.core.layout.WindowWidthSizeClass EXPANDED;
+    property @Deprecated public androidx.window.core.layout.WindowWidthSizeClass MEDIUM;
   }
 
 }
diff --git a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowHeightSizeClass.kt b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowHeightSizeClass.kt
index e69a63f..1eccac7 100644
--- a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowHeightSizeClass.kt
+++ b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowHeightSizeClass.kt
@@ -16,9 +16,6 @@
 
 package androidx.window.core.layout
 
-import androidx.window.core.layout.WindowHeightSizeClass.Companion.COMPACT
-import androidx.window.core.layout.WindowHeightSizeClass.Companion.EXPANDED
-import androidx.window.core.layout.WindowHeightSizeClass.Companion.MEDIUM
 import kotlin.jvm.JvmField
 
 /**
@@ -27,6 +24,8 @@
  * type. It is possible to have resizeable windows in different device types. The viewport might
  * change from a [COMPACT] all the way to an [EXPANDED] size class.
  */
+@Suppress("DEPRECATION")
+@Deprecated("WindowHeightSizeClass will not be developed further, use WindowSizeClass instead.")
 class WindowHeightSizeClass private constructor(private val rawValue: Int) {
 
     override fun toString(): String {
@@ -56,16 +55,22 @@
 
     companion object {
         /** A bucket to represent a compact height, typical for a phone that is in landscape. */
-        @JvmField val COMPACT: WindowHeightSizeClass = WindowHeightSizeClass(0)
+        @Deprecated("WindowHeightSizeClass not be developed further.")
+        @JvmField
+        val COMPACT: WindowHeightSizeClass = WindowHeightSizeClass(0)
 
         /** A bucket to represent a medium height, typical for a phone in portrait or a tablet. */
-        @JvmField val MEDIUM: WindowHeightSizeClass = WindowHeightSizeClass(1)
+        @Deprecated("WindowHeightSizeClass not be developed further.")
+        @JvmField
+        val MEDIUM: WindowHeightSizeClass = WindowHeightSizeClass(1)
 
         /**
          * A bucket to represent an expanded height window, typical for a large tablet or a desktop
          * form-factor.
          */
-        @JvmField val EXPANDED: WindowHeightSizeClass = WindowHeightSizeClass(2)
+        @Deprecated("WindowHeightSizeClass not be developed further.")
+        @JvmField
+        val EXPANDED: WindowHeightSizeClass = WindowHeightSizeClass(2)
 
         /**
          * Returns a recommended [WindowHeightSizeClass] for the height of a window given the height
@@ -75,6 +80,7 @@
          * @return A recommended size class for the height
          * @throws IllegalArgumentException if the height is negative
          */
+        @Deprecated("WindowHeightSizeClass not be developed further.")
         internal fun compute(dpHeight: Float): WindowHeightSizeClass {
             require(dpHeight >= 0) { "Height must be positive, received $dpHeight" }
             return when {
diff --git a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClass.kt b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClass.kt
index 9df0361..43bef20 100644
--- a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClass.kt
+++ b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClass.kt
@@ -16,30 +16,28 @@
 
 package androidx.window.core.layout
 
-import androidx.window.core.ExperimentalWindowCoreApi
+import kotlin.jvm.JvmField
 import kotlin.jvm.JvmStatic
 
 /**
- * [WindowSizeClass] represents breakpoints for a viewport. The recommended width and height break
- * points are presented through [windowWidthSizeClass] and [windowHeightSizeClass]. Designers should
- * design around the different combinations of width and height buckets. Developers should use the
- * different buckets to specify the layouts. Ideally apps will work well in each bucket and by
- * extension work well across multiple devices. If two devices are in similar buckets they should
- * behave similarly.
+ * [WindowSizeClass] represents breakpoints for a viewport. Designers should design around the
+ * different combinations of width and height buckets. Developers should use the different buckets
+ * to specify the layouts. Ideally apps will work well in each bucket and by extension work well
+ * across multiple devices. If two devices are in similar buckets they should behave similarly.
  *
  * This class is meant to be a common definition that can be shared across different device types.
- * Application developers can use WindowSizeClass to have standard window buckets and design the UI
- * around those buckets. Library developers can use these buckets to create different UI with
+ * Application developers can use [WindowSizeClass] to have standard window buckets and design the
+ * UI around those buckets. Library developers can use these buckets to create different UI with
  * respect to each bucket. This will help with consistency across multiple device types.
  *
  * A library developer use-case can be creating some navigation UI library. For a size class with
- * the [WindowWidthSizeClass.EXPANDED] width it might be more reasonable to have a side navigation.
- * For a [WindowWidthSizeClass.COMPACT] width, a bottom navigation might be a better fit.
+ * the [WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND] width it might be more reasonable to have a
+ * side navigation.
  *
  * An application use-case can be applied for apps that use a list-detail pattern. The app can use
- * the [WindowWidthSizeClass.MEDIUM] to determine if there is enough space to show the list and the
- * detail side by side. If all apps follow this guidance then it will present a very consistent user
- * experience.
+ * the [WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND] to determine if there is enough space to show
+ * the list and the detail side by side. If all apps follow this guidance then it will present a
+ * very consistent user experience.
  *
  * In some cases developers or UI systems may decide to create their own break points. A developer
  * might optimize for a window that is smaller than the supported break points or larger. A UI
@@ -50,13 +48,58 @@
  * @see WindowWidthSizeClass
  * @see WindowHeightSizeClass
  */
-class WindowSizeClass
-private constructor(
+class WindowSizeClass(
+    /** Returns the lower bound for the width of the size class in dp. */
+    val minWidthDp: Int,
+    /** Returns the lower bound for the height of the size class in dp. */
+    val minHeightDp: Int
+) {
+
+    /** A convenience constructor that will truncate to ints. */
+    constructor(widthDp: Float, heightDp: Float) : this(widthDp.toInt(), heightDp.toInt())
+
+    init {
+        require(minWidthDp >= 0) {
+            "Expected minWidthDp to be at least 0, minWidthDp: $minWidthDp."
+        }
+        require(minHeightDp >= 0) {
+            "Expected minHeightDp to be at least 0, minHeightDp: $minHeightDp."
+        }
+    }
+
+    @Suppress("DEPRECATION")
+    @Deprecated("Use either isWidthAtLeast or isAtLeast to check matching bounds.")
     /** Returns the [WindowWidthSizeClass] that corresponds to the widthDp of the window. */
-    val windowWidthSizeClass: WindowWidthSizeClass,
+    val windowWidthSizeClass: WindowWidthSizeClass
+        get() = WindowWidthSizeClass.compute(minWidthDp.toFloat())
+
+    @Suppress("DEPRECATION")
+    @Deprecated("Use either isHeightAtLeast or isAtLeast to check matching bounds.")
     /** Returns the [WindowHeightSizeClass] that corresponds to the heightDp of the window. */
     val windowHeightSizeClass: WindowHeightSizeClass
-) {
+        get() = WindowHeightSizeClass.compute(minHeightDp.toFloat())
+
+    /**
+     * Returns `true` when [widthDp] is greater than or equal to [minWidthDp], `false` otherwise.
+     */
+    fun isWidthAtLeast(widthDp: Int): Boolean {
+        return widthDp >= minWidthDp
+    }
+
+    /**
+     * Returns `true` when [heightDp] is greater than or equal to [minHeightDp], `false` otherwise.
+     */
+    fun isHeightAtLeast(heightDp: Int): Boolean {
+        return heightDp >= minHeightDp
+    }
+
+    /**
+     * Returns `true` when [widthDp] is greater than or equal to [minWidthDp] and [heightDp] is
+     * greater than or equal to [minHeightDp], `false` otherwise.
+     */
+    fun isAtLeast(widthDp: Int, heightDp: Int): Boolean {
+        return isWidthAtLeast(widthDp) && isHeightAtLeast(heightDp)
+    }
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
@@ -64,25 +107,49 @@
 
         other as WindowSizeClass
 
-        if (windowWidthSizeClass != other.windowWidthSizeClass) return false
-        if (windowHeightSizeClass != other.windowHeightSizeClass) return false
+        if (minWidthDp != other.minWidthDp) return false
+        if (minHeightDp != other.minHeightDp) return false
 
         return true
     }
 
     override fun hashCode(): Int {
-        var result = windowWidthSizeClass.hashCode()
-        result = 31 * result + windowHeightSizeClass.hashCode()
+        var result = minWidthDp
+        result = 31 * result + minHeightDp
         return result
     }
 
     override fun toString(): String {
-        return "WindowSizeClass {" +
-            "windowWidthSizeClass=$windowWidthSizeClass, " +
-            "windowHeightSizeClass=$windowHeightSizeClass }"
+        return "WindowSizeClass(minWidthDp=$minWidthDp, minHeightDp=$minHeightDp)"
     }
 
     companion object {
+        /** A lower bound for a size class with Medium width in dp. */
+        const val WIDTH_DP_MEDIUM_LOWER_BOUND = 600
+
+        /** A lower bound for a size class with Expanded width in dp. */
+        const val WIDTH_DP_EXPANDED_LOWER_BOUND = 840
+
+        /** A lower bound for a size class with Medium height in dp. */
+        const val HEIGHT_DP_MEDIUM_LOWER_BOUND = 480
+
+        /** A lower bound for a size class with Expanded height in dp. */
+        const val HEIGHT_DP_EXPANDED_LOWER_BOUND = 900
+
+        private val WIDTH_DP_BREAKPOINTS_V1 =
+            listOf(WIDTH_DP_MEDIUM_LOWER_BOUND, WIDTH_DP_EXPANDED_LOWER_BOUND)
+
+        private val HEIGHT_DP_BREAKPOINTS_V1 =
+            listOf(HEIGHT_DP_MEDIUM_LOWER_BOUND, HEIGHT_DP_EXPANDED_LOWER_BOUND)
+
+        @JvmField
+        val BREAKPOINTS_V1 =
+            WIDTH_DP_BREAKPOINTS_V1.flatMap { widthBp ->
+                    HEIGHT_DP_BREAKPOINTS_V1.map { heightBp ->
+                        WindowSizeClass(minWidthDp = widthBp, minHeightDp = heightBp)
+                    }
+                }
+                .toSet()
 
         /**
          * Computes the recommended [WindowSizeClass] for the given width and height in DP.
@@ -93,28 +160,21 @@
          * @throws IllegalArgumentException if [dpWidth] or [dpHeight] is negative.
          */
         @JvmStatic
+        @Deprecated("Use the constructor instead.")
         fun compute(dpWidth: Float, dpHeight: Float): WindowSizeClass {
-            return WindowSizeClass(
-                WindowWidthSizeClass.compute(dpWidth),
-                WindowHeightSizeClass.compute(dpHeight)
-            )
-        }
-
-        /**
-         * Computes the [WindowSizeClass] for the given width and height in pixels with density.
-         *
-         * @param widthPx width of a window in PX.
-         * @param heightPx height of a window in PX.
-         * @param density density of the display where the window is shown.
-         * @return [WindowSizeClass] that is recommended for the given dimensions.
-         * @throws IllegalArgumentException if [widthPx], [heightPx], or [density] is negative.
-         */
-        @JvmStatic
-        @ExperimentalWindowCoreApi
-        fun compute(widthPx: Int, heightPx: Int, density: Float): WindowSizeClass {
-            val widthDp = widthPx / density
-            val heightDp = heightPx / density
-            return compute(widthDp, heightDp)
+            val widthDp =
+                when {
+                    dpWidth >= WIDTH_DP_EXPANDED_LOWER_BOUND -> WIDTH_DP_EXPANDED_LOWER_BOUND
+                    dpWidth >= WIDTH_DP_MEDIUM_LOWER_BOUND -> WIDTH_DP_MEDIUM_LOWER_BOUND
+                    else -> 0
+                }
+            val heightDp =
+                when {
+                    dpHeight >= HEIGHT_DP_EXPANDED_LOWER_BOUND -> HEIGHT_DP_EXPANDED_LOWER_BOUND
+                    dpHeight >= HEIGHT_DP_MEDIUM_LOWER_BOUND -> HEIGHT_DP_MEDIUM_LOWER_BOUND
+                    else -> 0
+                }
+            return WindowSizeClass(widthDp, heightDp)
         }
     }
 }
diff --git a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClassSelectors.kt b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClassSelectors.kt
new file mode 100644
index 0000000..25ef7c0
--- /dev/null
+++ b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowSizeClassSelectors.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+@file:JvmName("WindowSizeClassSelectors")
+
+package androidx.window.core.layout
+
+import kotlin.jvm.JvmName
+
+/**
+ * Returns the largest [WindowSizeClass] that is within the bounds of ([widthDp], [heightDp]). This
+ * method prefers width and uses max height to break ties. If there is no match a default of
+ * `WindowSizeClass(0,0)` is returned. Examples: Input: Set: `setOf(WindowSizeClass(300, 300),
+ * WindowSizeClass(300, 600)` widthDp: `300` heightDp: `800` Output: `WindowSizeClass(300, 600)`
+ * Input: Set: `setOf(WindowSizeClass(300, 300), WindowSizeClass(300, 600)` widthDp: `300` heightDp:
+ * `400` Output: `WindowSizeClass(300, 300)`
+ *
+ * @param widthDp the width of the window to match a [WindowSizeClass] to.
+ * @param heightDp the height of the window to match a [WindowSizeClass] to.
+ */
+fun Set<WindowSizeClass>.computeWindowSizeClass(widthDp: Int, heightDp: Int): WindowSizeClass {
+    var maxWidth = 0
+    forEach { bucket ->
+        if (bucket.minWidthDp <= widthDp && bucket.minWidthDp > maxWidth) {
+            maxWidth = bucket.minWidthDp
+        }
+    }
+    var match = WindowSizeClass(0, 0)
+    forEach { bucket ->
+        if (
+            bucket.minWidthDp == maxWidth &&
+                bucket.minHeightDp <= heightDp &&
+                match.minHeightDp < bucket.minHeightDp
+        ) {
+            match = bucket
+        }
+    }
+    return match
+}
+
+/**
+ * Returns the largest [WindowSizeClass] that is within the bounds of ([widthDp], [heightDp]). This
+ * method prefers height and uses max width to break ties. If there is no match a default of
+ * `WindowSizeClass(0,0)` is returned. Examples: Input: Set: `setOf(WindowSizeClass(300, 300),
+ * WindowSizeClass(600, 300)` widthDp: `800` heightDp: `300` Output: `WindowSizeClass(600, 300)`
+ * Input: Set: `setOf(WindowSizeClass(300, 300), WindowSizeClass(600, 300)` widthDp: `400` heightDp:
+ * `300` Output: `WindowSizeClass(300, 300)`
+ *
+ * @param widthDp the width of the window to match a [WindowSizeClass] to.
+ * @param heightDp the height of the window to match a [WindowSizeClass] to.
+ */
+fun Set<WindowSizeClass>.computeWindowSizeClassPreferHeight(
+    widthDp: Int,
+    heightDp: Int
+): WindowSizeClass {
+    var maxHeight = 0
+    forEach { bucket ->
+        if (bucket.minHeightDp <= heightDp && bucket.minHeightDp > maxHeight) {
+            maxHeight = bucket.minHeightDp
+        }
+    }
+    var match = WindowSizeClass(0, 0)
+    forEach { bucket ->
+        if (
+            bucket.minHeightDp == maxHeight &&
+                bucket.minWidthDp <= widthDp &&
+                match.minWidthDp < bucket.minWidthDp
+        ) {
+            match = bucket
+        }
+    }
+    return match
+}
diff --git a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowWidthSizeClass.kt b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowWidthSizeClass.kt
index 11af3a0..3097d8f 100644
--- a/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowWidthSizeClass.kt
+++ b/window/window-core/src/commonMain/kotlin/androidx/window/core/layout/WindowWidthSizeClass.kt
@@ -24,7 +24,10 @@
  * type. It is possible to have resizeable windows in different device types. The viewport might
  * change from a [COMPACT] all the way to an [EXPANDED] size class.
  */
+@Suppress("DEPRECATION")
+@Deprecated("WindowWidthSizeClass will not be developed further, use WindowSizeClass instead.")
 class WindowWidthSizeClass private constructor(private val rawValue: Int) {
+
     override fun toString(): String {
         val name =
             when (this) {
@@ -52,19 +55,25 @@
 
     companion object {
         /** A bucket to represent a compact width window, typical for a phone in portrait. */
-        @JvmField val COMPACT: WindowWidthSizeClass = WindowWidthSizeClass(0)
+        @Deprecated("WindowWidthSizeClass not be developed further.")
+        @JvmField
+        val COMPACT: WindowWidthSizeClass = WindowWidthSizeClass(0)
 
         /**
          * A bucket to represent a medium width window, typical for a phone in landscape or a
          * tablet.
          */
-        @JvmField val MEDIUM: WindowWidthSizeClass = WindowWidthSizeClass(1)
+        @Deprecated("WindowWidthSizeClass not be developed further.")
+        @JvmField
+        val MEDIUM: WindowWidthSizeClass = WindowWidthSizeClass(1)
 
         /**
          * A bucket to represent an expanded width window, typical for a large tablet or desktop
          * form-factor.
          */
-        @JvmField val EXPANDED: WindowWidthSizeClass = WindowWidthSizeClass(2)
+        @Deprecated("WindowWidthSizeClass not be developed further.")
+        @JvmField
+        val EXPANDED: WindowWidthSizeClass = WindowWidthSizeClass(2)
 
         /**
          * Returns a recommended [WindowWidthSizeClass] for the width of a window given the width in
@@ -74,6 +83,7 @@
          * @return A recommended size class for the width
          * @throws IllegalArgumentException if the width is negative
          */
+        @Deprecated("WindowWidthSizeClass not be developed further.")
         internal fun compute(dpWidth: Float): WindowWidthSizeClass {
             require(dpWidth >= 0) { "Width must be positive, received $dpWidth" }
             return when {
diff --git a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowHeightSizeClassTest.kt b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowHeightSizeClassTest.kt
index 80868cf..7183670 100644
--- a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowHeightSizeClassTest.kt
+++ b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowHeightSizeClassTest.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("DEPRECATION")
+
 package androidx.window.core.layout
 
 import androidx.window.core.layout.WindowHeightSizeClass.Companion.COMPACT
diff --git a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassSelectorsTest.kt b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassSelectorsTest.kt
new file mode 100644
index 0000000..f72e378
--- /dev/null
+++ b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassSelectorsTest.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.window.core.layout
+
+import androidx.window.core.layout.WindowSizeClass.Companion.HEIGHT_DP_MEDIUM_LOWER_BOUND
+import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_MEDIUM_LOWER_BOUND
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class WindowSizeClassSelectorsTest {
+
+    val coreSet = WindowSizeClass.BREAKPOINTS_V1
+
+    @Test
+    fun compute_window_size_class_returns_zero_for_default() {
+        // coreSet does not contain 10, 10
+        val actual = coreSet.computeWindowSizeClass(10, 10)
+
+        assertEquals(WindowSizeClass(0, 0), actual)
+    }
+
+    @Test
+    fun compute_window_size_class_returns_exact_match() {
+        val expected = WindowSizeClass(WIDTH_DP_MEDIUM_LOWER_BOUND, HEIGHT_DP_MEDIUM_LOWER_BOUND)
+
+        // coreSet contains WindowSizeClass(MEDIUM, MEDIUM)
+        val actual =
+            coreSet.computeWindowSizeClass(
+                WIDTH_DP_MEDIUM_LOWER_BOUND,
+                HEIGHT_DP_MEDIUM_LOWER_BOUND
+            )
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_returns_bounded_match() {
+        val expected = WindowSizeClass(WIDTH_DP_MEDIUM_LOWER_BOUND, HEIGHT_DP_MEDIUM_LOWER_BOUND)
+
+        // coreSet contains WindowSizeClass(MEDIUM, MEDIUM)
+        val actual =
+            coreSet.computeWindowSizeClass(
+                WIDTH_DP_MEDIUM_LOWER_BOUND + 1,
+                HEIGHT_DP_MEDIUM_LOWER_BOUND + 1
+            )
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_prefers_width() {
+        val expected = WindowSizeClass(minWidthDp = 100, minHeightDp = 50)
+
+        val actual =
+            setOf(
+                    WindowSizeClass(minWidthDp = 100, minHeightDp = 50),
+                    WindowSizeClass(minWidthDp = 50, minHeightDp = 100)
+                )
+                .computeWindowSizeClass(100, 100)
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_breaks_tie_with_height() {
+        val expected = WindowSizeClass(minWidthDp = 100, minHeightDp = 100)
+
+        val actual =
+            setOf(
+                    WindowSizeClass(minWidthDp = 100, minHeightDp = 50),
+                    WindowSizeClass(minWidthDp = 100, minHeightDp = 100)
+                )
+                .computeWindowSizeClass(200, 200)
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_preferring_height_returns_zero_for_default() {
+        // coreSet does not contain 10, 10
+        val actual = coreSet.computeWindowSizeClassPreferHeight(10, 10)
+
+        assertEquals(WindowSizeClass(0, 0), actual)
+    }
+
+    @Test
+    fun compute_window_size_class_preferring_height_returns_exact_match() {
+        val expected = WindowSizeClass(WIDTH_DP_MEDIUM_LOWER_BOUND, HEIGHT_DP_MEDIUM_LOWER_BOUND)
+
+        // coreSet contains WindowSizeClass(MEDIUM, MEDIUM)
+        val actual =
+            coreSet.computeWindowSizeClassPreferHeight(
+                WIDTH_DP_MEDIUM_LOWER_BOUND,
+                HEIGHT_DP_MEDIUM_LOWER_BOUND
+            )
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_preferring_height_returns_bounded_match() {
+        val expected = WindowSizeClass(WIDTH_DP_MEDIUM_LOWER_BOUND, HEIGHT_DP_MEDIUM_LOWER_BOUND)
+
+        // coreSet contains WindowSizeClass(MEDIUM, MEDIUM)
+        val actual =
+            coreSet.computeWindowSizeClassPreferHeight(
+                WIDTH_DP_MEDIUM_LOWER_BOUND + 1,
+                HEIGHT_DP_MEDIUM_LOWER_BOUND + 1
+            )
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_preferring_height_prefers_height() {
+        val expected = WindowSizeClass(minWidthDp = 50, minHeightDp = 100)
+
+        val actual =
+            setOf(
+                    WindowSizeClass(minWidthDp = 100, minHeightDp = 50),
+                    WindowSizeClass(minWidthDp = 50, minHeightDp = 100)
+                )
+                .computeWindowSizeClassPreferHeight(100, 100)
+
+        assertEquals(expected, actual)
+    }
+
+    @Test
+    fun compute_window_size_class_preferring_height_breaks_tie_with_width() {
+        val expected = WindowSizeClass(minWidthDp = 100, minHeightDp = 100)
+
+        val actual =
+            setOf(
+                    WindowSizeClass(minWidthDp = 50, minHeightDp = 100),
+                    WindowSizeClass(minWidthDp = 100, minHeightDp = 100)
+                )
+                .computeWindowSizeClass(200, 200)
+
+        assertEquals(expected, actual)
+    }
+}
diff --git a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassTest.kt b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassTest.kt
index 46607ab..816e40c 100644
--- a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassTest.kt
+++ b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowSizeClassTest.kt
@@ -16,16 +16,18 @@
 
 package androidx.window.core.layout
 
-import androidx.window.core.ExperimentalWindowCoreApi
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertFailsWith
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
 
 /** Tests for [WindowSizeClass] that verify construction. */
 class WindowSizeClassTest {
 
+    @Suppress("DEPRECATION")
     @Test
-    fun testWidthSizeClass_construction() {
+    fun testWindowWidthSizeClass_compatibility() {
         val expected =
             listOf(
                 WindowWidthSizeClass.COMPACT,
@@ -41,6 +43,7 @@
         assertEquals(expected, actual)
     }
 
+    @Suppress("DEPRECATION")
     @Test
     fun testWindowSizeClass_computeRounds() {
         val expected = WindowSizeClass.compute(0f, 0f)
@@ -50,18 +53,9 @@
         assertEquals(expected, actual)
     }
 
-    @OptIn(ExperimentalWindowCoreApi::class)
+    @Suppress("DEPRECATION")
     @Test
-    fun testConstruction_usingPx() {
-        val expected = WindowSizeClass.compute(600f, 600f)
-
-        val actual = WindowSizeClass.compute(600, 600, 1f)
-
-        assertEquals(expected, actual)
-    }
-
-    @Test
-    fun testHeightSizeClass_construction() {
+    fun testWindowHeightSizeClass_compatibility() {
         val expected =
             listOf(
                 WindowHeightSizeClass.COMPACT,
@@ -79,16 +73,17 @@
 
     @Test
     fun testEqualsImpliesHashCode() {
-        val first = WindowSizeClass.compute(100f, 500f)
-        val second = WindowSizeClass.compute(100f, 500f)
+        val first = WindowSizeClass(100, 500)
+        val second = WindowSizeClass(100, 500)
 
         assertEquals(first, second)
         assertEquals(first.hashCode(), second.hashCode())
     }
 
+    @Suppress("DEPRECATION")
     @Test
     fun truncated_float_does_not_throw() {
-        val sizeClass = WindowSizeClass.compute(0.5f, 0.5f)
+        val sizeClass = WindowSizeClass(0.5f, 0.5f)
 
         val widthSizeClass = sizeClass.windowWidthSizeClass
         val heightSizeClass = sizeClass.windowHeightSizeClass
@@ -97,9 +92,10 @@
         assertEquals(WindowHeightSizeClass.COMPACT, heightSizeClass)
     }
 
+    @Suppress("DEPRECATION")
     @Test
     fun zero_size_class_does_not_throw() {
-        val sizeClass = WindowSizeClass.compute(0f, 0f)
+        val sizeClass = WindowSizeClass(0, 0)
 
         val widthSizeClass = sizeClass.windowWidthSizeClass
         val heightSizeClass = sizeClass.windowHeightSizeClass
@@ -110,11 +106,94 @@
 
     @Test
     fun negative_width_throws() {
-        assertFailsWith(IllegalArgumentException::class) { WindowSizeClass.compute(-1f, 0f) }
+        assertFailsWith(IllegalArgumentException::class) { WindowSizeClass(-1, 0) }
     }
 
     @Test
     fun negative_height_throws() {
-        assertFailsWith(IllegalArgumentException::class) { WindowSizeClass.compute(0f, -1f) }
+        assertFailsWith(IllegalArgumentException::class) { WindowSizeClass(0, -1) }
+    }
+
+    @Test
+    fun is_width_at_least_returns_true_when_input_is_greater() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertTrue(sizeClass.isWidthAtLeast(width + 1))
+    }
+
+    @Test
+    fun is_width_at_least_returns_true_when_input_is_equal() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertTrue(sizeClass.isWidthAtLeast(width))
+    }
+
+    @Test
+    fun is_width_at_least_returns_false_when_input_is_smaller() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertFalse(sizeClass.isWidthAtLeast(width - 1))
+    }
+
+    @Test
+    fun is_height_at_least_returns_true_when_input_is_greater() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertTrue(sizeClass.isHeightAtLeast(height + 1))
+    }
+
+    @Test
+    fun is_height_at_least_returns_true_when_input_is_equal() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertTrue(sizeClass.isHeightAtLeast(height))
+    }
+
+    @Test
+    fun is_height_at_least_returns_false_when_input_is_smaller() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertFalse(sizeClass.isHeightAtLeast(height - 1))
+    }
+
+    @Test
+    fun is_at_least_returns_true_when_input_is_greater() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertTrue(sizeClass.isAtLeast(width, height + 1))
+        assertTrue(sizeClass.isAtLeast(width + 1, height))
+    }
+
+    @Test
+    fun is_at_least_returns_true_when_input_is_equal() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertTrue(sizeClass.isAtLeast(width, height))
+    }
+
+    @Test
+    fun is_at_least_returns_false_when_input_is_smaller() {
+        val width = 200
+        val height = 100
+        val sizeClass = WindowSizeClass(width, height)
+
+        assertFalse(sizeClass.isAtLeast(width, height - 1))
+        assertFalse(sizeClass.isAtLeast(width - 1, height))
     }
 }
diff --git a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowWidthSizeClassTest.kt b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowWidthSizeClassTest.kt
index 85ab99b..520b9bf 100644
--- a/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowWidthSizeClassTest.kt
+++ b/window/window-core/src/commonTest/kotlin/androidx/window/core/layout/WindowWidthSizeClassTest.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("DEPRECATION")
+
 package androidx.window.core.layout
 
 import androidx.window.core.layout.WindowWidthSizeClass.Companion.COMPACT
diff --git a/window/window-demos/demo/src/main/java/androidx/window/demo/coresdk/WindowStateScreen.kt b/window/window-demos/demo/src/main/java/androidx/window/demo/coresdk/WindowStateScreen.kt
index 92e85eb..3ff2766 100644
--- a/window/window-demos/demo/src/main/java/androidx/window/demo/coresdk/WindowStateScreen.kt
+++ b/window/window-demos/demo/src/main/java/androidx/window/demo/coresdk/WindowStateScreen.kt
@@ -154,7 +154,7 @@
                 activityDisplayBounds = Rect(0, 0, 960, 2142),
             ),
         )
-    DemoTheme { WindowStateScreen(viewModel = WindowStateViewModel(windowStates)) }
+    DemoTheme { WindowStateScreen(viewModel = viewModel { WindowStateViewModel(windowStates) }) }
 }
 
 /**